go 语言中的struct
Go的struct声明允许字段附带Tag来对字段进行一些标记,Tag的主要作用在反射场景,refelect 包提供了操作tag的方法。
Tag
Tag本身是结构体字段的一个组成部分,是一个字符串,格式是:以空格分割的key:value对。
type StructField struct {
Name string
Tag StructTag
}
type StructTag string
key : 必须是非空字符串,字符串不能包括控制字符、空格、引号、冒号。
value : 以双引号标记的字符串
key:value,“ : ”不能有空格
type server struct {
server string `key1:"value1" key11:"value11"`
server1 string `key1:"value1"`
}
获取方式:
```go
func main() {
s := Server{}
st := reflect.TypeOf(s)
field1 := st.Field(0)
fmt.Printf("key1:%v\n", field1.Tag.Get("key1"))
fmt.Printf("key11:%v\n", field1.Tag.Get("key11"))
field2 := st.Field(1)
fmt.Printf("key2:%v\n", field2.Tag.Get("key2"))
}
Tag存在的意义
使用反射可以动态的给结构体成员赋值,正是因为有tag,在赋值前可以使用tag来决定赋值的动作。比如,官方 的 encoding/json 包,可以将一个JSON数据 Unmarshal 进一个结构体,此过程中就使用了Tag. 该包定义一些规 则,只要参考该规则设置tag就可以将不同的JSON数据转换成结构体。 总之:正是基于struct的tag特性,才有了诸如json、orm等等的应用。理解这个关系是至关重要的。或许,你可以 定义另一种tag规则,来处理你特有的数据。
空结构体的作用
如果结构体没有任何成员的话就是空结构体,写作struct{}。它的大小为0,也不包含任何信息,但是有时候依然是有价值的。有些Go语言程序员用map来模拟set数据结构时,用它来代替map中布尔类型的value,只是强调key的重要性,但是因为节约的空间有限,而且语法比较复杂,所以我们通常会避免这样的用法。
seen := make(map[string]struct{}) // set of strings
// ...
if _, ok := seen[s]; !ok {
seen[s] = struct{}{}
// ...first time seeing s...
}
结构体的比较
如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的,那样的话两个结构体将可以使用或!=运算符进行比较。相等比较运算符将比较两个结构体的每个成员,因此下面两个比较的表达式是等价的:
type Point struct{ X, Y int }
p := Point{1, 2}
q := Point{2, 1}
fmt.Println(p.X == q.X && p.Y == q.Y) // "false"
fmt.Println(p == q) // "false"
type Point2 struct{ X, Y int }
p := Point{1, 2}
q := Point2{1, 2}
fmt.Println(p.X == q.X && p.Y == q.Y) // "true"
fmt.Println(p == q) // "编译不通过"
type Point struct{
Id int
Name string
HH map[string]string }
p := Point{1, 2}
q := Point{2, 1}
fmt.Println(p == q) // "编译不通过"
可比较的结构体类型和其他可比较的类型一样,可以用于map的key类型。
type address struct {
hostname string
port int
}
hits := make(map[address]int)
hits[address{"golang.org", 443}]++