欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

goalng struct剖析(嵌套结构体/匿名结构体/tag)

程序员文章站 2022-07-12 22:58:37
...

goalng struct

目录

goalng struct

结构体(struct)

结构体嵌套

匿名结构体

Tag

Tag的本质

 获取Tag

Tag存在的意义

Tag常见用法


结构体(struct)

结构体是用户自定义的类型,它代表若干字段的集合,可以用于描述一个实体对象,类似Java中的Class,是golang面向对象编程的基础类型.

因为 Go 语言中没有类的概念,所以在 Go 中结构体有着更为重要的地位

语法:type <Name> struct{}

添加对象方法: func(t *T) funcName(){}

初始化的方法:

#按原始字段顺序创建结构体
 p := T{1, 2}

#照自定义字段顺序进行初始化
 p := T{Y:1, X:2}

#通过new函数创建
p1 := new(T)
T.X = 1
T.Y = 2

 

结构体嵌套

go中使用结构体嵌套来扩展类型

嵌入到结构体中的字段,完全可以当作自己是自己的字段


type ST struct{ X, Y float64 }

type FT struct {
    ST 
    Value int
}

结构体FT嵌套了结构体ST,此时FT就拥有了ST的字段X,Y.可以通过“.”来操作,如果ST拥有自己的方法,那么FT也可以使用这些方法,而不需要自己再定义.

用这种方式,内嵌可以使我们定义字段特别多的复杂类型,我们可以将字段先按小类型分组,然后定义小类型的方法,之后再把它们组合起来

编译器查找方法的顺序:

  1. 先在本结构体定义的方法中找
  2. 找不到,再去子结构体找,然后一直递归向下找

如果选择器有二义性的话编译器会报错,比如你有一个字段叫Test,然后一个方法也叫Test,那么选择器就不知道你想使用的是哪个,编译器就会报错

 

匿名结构体

匿名结构体就是在嵌入时,不指定名称,这样子会将匿名结果体的所有方法引入到该类型中;这样在使用时有很多便利:例如下面对map的操作;

我们知道map时非线程安全的,会存在读或写竞争,我们需要在对map的操作时进行加锁

package main

// 匿名结构提嵌套,可以引入匿名结构体所有的方法
import (
    "fmt"
    "sync"
)

type safeMap struct {
    sync.Mutex
    mapping map[string]string
}

// 获取map中元素的值
func (m safeMap) Get(key string) (value string) {
  	// 引入了sync.Mutex的加锁和解锁方法
    m.Lock()
    value = m.mapping[key]
    m.Unlock()
    return
}

func main() {
    m := map[string]string{
        "a" : "alpha",
        "i" : "integer",
    }

    cache := safeMap{
        mapping: m,
    }

    fmt.Println(cache.Get("a"))
    fmt.Println(cache.Get("i"))
}

因为sync.Mutex字段也被嵌入到了这个struct里,其Lock和Unlock方法也就都被引入到了这个匿名结构中了,这让我们能够以一个简单明了的语法来对其进行加锁解锁操作

 

Tag

Go的struct声明允许字段附带Tag来对字段做一些标记.

该Tag不仅仅是一个字符串那么简单,因为其主要用于反射场景, reflect包中提供了操作Tag的方法,所以Tag写法也要遵循一定的规则.

Tag的本质

Tag的规则

Tag本身是一个字符串,当字符串却是 以空格分隔的key:value对

  • key:必须是非空字符串,字符串不能包含控制字符.空格.引号.冒号.
  • value:以双引号标记的字符串.
  • 注意:冒号前后不能有空格

Tag字符说明:

type Server struct{

    ServerName string `key1:"value1" key2:"value2"`

    ServerIp   string `key2:"value3`
}
 
Tag是struct的一部分
 
Tag只有在反射场景中才有用,而反射包中提供了操作Tag的方法.
 
reflect包中的类型声明:
// A StructField describes a single field in a struct.
type StructField struct {

    // Name is the field name.
    Name string

    ...

    Type Type // field type

    Tag StructTag // field tag string
    
    ...
}

type StructTag string
可见,描述一个结构体成员的结构体中包含了 StructTag, 而其本身是一个 string.也就是说Tag其实是结构体字段的一个组成部分.
 
 
 

 获取Tag

StructTag 提供了 Get(key string)string 方法来获取Tag

goalng struct剖析(嵌套结构体/匿名结构体/tag)

 
goalng struct剖析(嵌套结构体/匿名结构体/tag)
 
 
 

Tag存在的意义

使用反射可以动态的给结构体成员赋值,正是因为有tag,在赋值前可以使用tag来决定赋值的动作.

比如,官方的 encoding/json 包,可以将一个JSON数据 Unmarshal 进一个结构体,此过程中就是用了Tag,该包定义一些规则,

只要参考改规则设置tag就可以将不同的JSON数据转换成结构体.

总之:正是基于struct的tag特性,才有了诸如json. orm等等的应用.理解这个关系是至关重要的.或许,你可以定义另一种tag规则,来处理你特有的数据.

 

Tag常见用法

常见的Tag用法,主要是JSON数据解析,ORM映射等.

 
 
 

参考内容:

https://www.cnblogs.com/vinsent/p/11536637.html

《GO 专家编程》