zoukankan      html  css  js  c++  java
  • Go语言中的Struct

    一、Go语言中没有像C#、Java一样的Class,只有Struct这样的结构体。Go语言使用type关键字来定义一个类型。

    如下:

    type User struct {
       Name string
       Age int32
       Sex int16
       AvatarUrl string
    }
    

    二、Struct的声明以及初始化

    初始化方法一:直接定义,通过变量名.成员名的方式赋值

    //初始化方法1
    var user1 User
    user1.Name = "BigOrange"
    user1.Age = 20
    user1.Sex = 1
    user1.AvatarUrl = "xxxxxxx"
    
    fmt.Println("User1:",user1)
    

    初始化方法二:直接通过{}进行初始化,这点和C#不一样,C#初始化的时候一般用new,例如 var user  = new User{xxxxx,xxxxx,xxxx}

    //初始化方法2
    var user2 User = User{
       Name:"BigBanana",
       Age:23,
       Sex:0,
       AvatarUrl:"yyyyyyyyyyy",
    }
    
    fmt.Println("User2:",user2)
    
    //初始化方法2简化
     user3 := User{
       Name:"BigBanana",
       Age:23,
       Sex:0,
       AvatarUrl:"yyyyyyyyyyy",
    }
    
    fmt.Println("User3:",user3)
    

      

    三、Struct的指针

    Struct的指针比较简单,就是通过&获取地址,此外还可以用new来返回一个对象的指针

    var user4 *User = &User{
        Name:"BigPeach",
        Age:22,
        Sex:1,
        AvatarUrl:"zzzzzzz",
     }
    
    fmt.Println("User4:",user4)
    fmt.Println("User4:",*user4)
    

     

    user5 := new(User)
    user5.Name="BigGrape"
    user5.Age= 25
    user5.Sex= 1
    user5.AvatarUrl= "mmmmmmmmm"
    fmt.Println("User5:",user5)
    fmt.Println("User5:",*user5)
    

    上面第二种方式可能会有些疑问,user5不是一个指针类型吗?怎么和上面的值类型一样直接用【变量名.成员】 的方式进行赋值了呢? 不是应该 (*user5).Name 这样吗?没有错!

    这是GO语言实现的一个语法糖,实际上GO语言会帮我转换。

     

    四、Struct成员的内存布局以及实现构造函数

    例如下面这样的一段代码

    package main
    
    import "fmt"
    
    type AddressDemo struct {
       addr1 int32
       addr2 int32
       addr3 int32
    }
    
    func main(){
       addr := new(AddressDemo)
       fmt.Println("add1地址:",&addr.addr1)
       fmt.Println("add2地址:",&addr.addr2)
       fmt.Println("add3地址:",&addr.addr3)
    }
    

    结果:

    add1地址: 0xc042060080
    add2地址: 0xc042060084
    add3地址: 0xc042060088
    

    可以看出来,addr1、addr2、addr3都是int32,都是占用了4个字节,他们的地址分配都是连续的

    For example: 下面这个User包,就实现了一个NewUser的方法,他就是构造函数

    package User
    
    type User struct {
       Name string
       Age int32
       Sex int16
       AvatarUrl string
    }
    
    func NewUser(name string , age int32,sex int16,avatarUrl string) *User{
       user:=new(User)
       user.Name = name
       user.Age = age
       user.Sex = sex
       user.AvatarUrl = avatarUrl
    
       return user
    }
    

    五、Struct中的匿名字段和嵌套

    可以像下面这样声明:后两个字段没有名字

    type Class struct {
       Name string
       int
       string
    }
    

    使用的时候,对于匿名的字段,直接赋值就可以了

    class1:=Class{
       Name:"Class1",
       int:123,
       string:"sssssss",
    }
    
    fmt.Println("class1:",class1)
    

    结构体的嵌套

    type User struct {
       Name string
       Age int32
       Sex int16
       AvatarUrl string
    }
    
    type Class struct {
       Name string
    }
    
    type Student struct {
       User User
       Class Class
    }
    

    使用:

    func main() {
       stu:=new(User.Student)
       
       stu.Class = User.Class{
          Name:"5-2",
       }
       
       stu.User = User.User {
           Name:"BigBanana",
          Sex:1,
          Age:12,
          AvatarUrl:"asdasdasd",
       }
       
       fmt.Println(stu)
    }
    

    如果是匿名结构体嵌套呢?修改一下Student

    type Student struct {
       User User
       Class
    }
    

    使用在对Class这个成员进行赋值的时候,可以发现,既可以使用

       stu.Class = User.Class{
          Name:"5-2",
       }
    

    也可以使用Name直接赋值,顺序就是现在当前的结构体找,找不到再从匿名结构体中查找,正好找到Class里面有Name

    stu.Name = "5-2"
    

    如果Class和User都是匿名结构嵌套,但是他们里面都有Name,当我们使用stu.Name的时候,那他访问的是Class里的Name还是User里面的Name? 那么岂不是冲突了? 如何处理冲突?

    当我试图给stu.Name赋值的时候,编译器报错了,内容如下,也就是它找不到应该给谁赋值。

    这时候要解决这个冲突,必须指定是哪个匿名字段里面的Name

    stu:=new(User.Student)
    
    stu.User.Name = "123123"
    stu.Class.Name = "5-2"
    
    stu.User = User.User {
       Name:"BigBanana",
       Sex:1,
       Age:12,
       AvatarUrl:"asdasdasd",
    }
    

     

    六、结构体内字段的可见性

    和包一样,小写的字段外部不可见,大写的外部可见

     

    七、结构体的Tag

    tag是结构体的元信息,可以在运行的时候通过反射的机制读出来。

    怎么写tag?

    以`作为开头和结尾,中间是key-value形式的字符串,每一个键值对以,作为分隔。例如

    type User struct {
       UserName string   `json:"userName",db:"User_Name"`
       Age int32         `json:"age"`
       Sex int16         `json:"sex"`
       AvatarUrl string  `json:"avatarUrl",db:"Avatar_Url"`
    }
    

    使用并运行:

    func main() {
    
       user := User.User {
          UserName:"BigBanana",
          Sex:1,
          Age:12,
          AvatarUrl:"asdasdasd",
       }
    
       fmt.Println(user)
    
       data,_:=json.Marshal(user)
    
       fmt.Println(string(data))
       
    }

    结果:

    {"userName":"BigBanana","age":12,"sex":1,"avatarUrl":"asdasdasd"}

    可以看到,如果打了这个tag,会显示tag后面的标记名称。

    此外:如果字段名称是小写,那么json输出的时候就不会有这个字段被打印了。

     

  • 相关阅读:
    java代码--Date类获取当前时间-格式化输出
    Eclipse快速生成do while if 等方法
    java不同包中protected修饰的属性和方法调用方法
    java中如果删除导入的jar包,工程出现叹号解决方案
    Best Reward HDU 3613(回文子串Manacher)
    Teacher YYF
    Period II
    How many
    String Problem
    Corporate Identity
  • 原文地址:https://www.cnblogs.com/dcz2015/p/10770917.html
Copyright © 2011-2022 走看看