Go进阶之struct

20 阅读3分钟

1.内嵌字段:

Go语言没有继承的概念.当需要复用其他结构体时.需要使用组合方式将其他结构体嵌

入当前结构体.

示例:

type People struct {
    Name string
}

func (p *People) SetName(name string) {
    p.Name = name
}

type Student struct {
    People
}

type Teacher struct {
   p People
}

结构体中的字段既可以显示指定也可以隐式指定.

注:显示指定和隐示指定没有区别.仅代表某种类型的字段.

1.1访问方式:

type People struct {
    Name string
}

func (p *People) SetName(name string) {
    p.Name = name
}

type Student struct {
    People
}

type Teacher struct {
    People
}

func main() {
    s := Student{}
    s.SetName("student")
    fmt.Println(s.Name)

    s.People.SetName("student2")
    fmt.Println(s.Name)

    s.People.Name = "student3"
    fmt.Println(s.Name)
}

2.访问受体:

一般函数声明:

func 函数名(参数){函数体}

方法声明:

func(接收者) 函数名(参数) {参数体}

方法一般用于类型的扩展方法.

示例:

type Student struct {
    People
}

func (s Student) SetName(name string) {
    s.Name = name
}

func (s *Student) UpdateName(name string) {
    s.Name = name
}

SetName()方法的接收者为Student.UpdateName()方法为Student.*

示例:

func main() {
    s := Student{}
    s.SetName("setName")
    fmt.Println(s.Name)
    s.UpdateName("updateName")
    fmt.Println(s.Name)
}

可以通过结果得知SetName()方法没有成功赋值.他两的执行逻辑虽然是一样的.但

是接收参数不一样.一个作用于对象.一个作用于指针.如果作用于对象.那么修改的是

当前对象的副本.如果作用指针.那么修改的是该对象的字段.

3.字段标签:

Go语言中Struct允许字段标记Tag.

示例:

type TypeMeta struct {
    Kind string `json:"kind" yaml:"kind" protobuf:"bytes,1,opt,name=kind"`
    Version string `json:"version"`
}

其中每个字段后面两个反引号中间的字符串就是Tag.

3.1Tag的本质:

3.1.1Tag是Struct的一部分:

Tag是用于标识结构体字段的额外属性.有点类似于注解.标准库reflect包中提供了操

作Tag的方法.

源码:runtime/reflect/type.go:StructField

type StructField struct {
    // Name is the field name.
    Name string

    // PkgPath is the package path that qualifies a lower case (unexported)
    // field name. It is empty for upper case (exported) field names.
    // See https://golang.org/ref/spec#Uniqueness_of_identifiers
    PkgPath string

    Type      Type      // field type
    Tag       StructTag // field tag string
    Offset    uintptr   // offset within struct, in bytes
    Index     []int     // index sequence for Type.FieldByIndex
    Anonymous bool      // is an embedded field
}

可以看出Tag也是字段的一个组成部分.Tag的类型为StructTag.实际上string类型的一个别名.如下所示.

type StructTag string

3.1.2Tag约定:

Tag本身是一个字符串.从单语义上讲.任意的字符串都是合法的.但有一个约定的格式.那就是key:value.

key:必须是非空字符串.字符串不能包含控制符 空格 引号 冒号.

value:以双引号标记的字符串.

注:key和value之间使用冒号分隔.冒号前后不能有空格,多个key:value之间由空格分开.

3.1.3获取Tag:
func main() {
    t := TypeMeta{}
    mType := reflect.TypeOf(t)
    for i := 0; i < mType.NumField(); i++ {
       fmt.Printf("Field name %s,Tag:%s\n", mType.Field(i).Name, mType.Field(i).Tag.Get("json"))
    }
}
3.1.4Tag的意义:

Go语言的反射特性可以动态的给结构体成员赋值.正式因为有Tag.在赋值前可以使用

Tag来决定赋值的动作.

悠然见南山.


如果大家喜欢我的分享的话.可以关注我的微信公众号

念何架构之路