在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Go语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。 type struct_name struct { name string talk Talk } 一旦定义了结构体类型,它就能用于变量的声明,语法格式如下: variable_name := structure_name{value1,value2} //顺序必须与结构体的定义一致 或者: variable_name := structure_name{key1:value1,key2:value2} //结构体名称:值
结构体类型中的每个字段都需要独占一行。一般情况下,字段声明需由字段名称和表示字段类型的字面量组成。 package main import "fmt" type node struct { _ int //没给值会使用默认值 id int next *node } func main() { n1 := node{ id: 1, } n2 := node{ id: 2, next: &n1, } fmt.Println(n1, n2) //{0 1 <nil>} {0 2 0xc000048400} }
可按顺序初始化全部字段,或使用命名方式初始化指定字段。 package main import "fmt" func main() { type user struct { name string age int } u1 := user{"Tom", 12} //如果顺序初始化字段,就必须赋值全部字段 u2 := user{"Kebi"} //too few values in user literal,字段数量不够 u3 := user{ //命名初始化 name: "maoixan", age: 18, } fmt.Println(u1, u3) }
推荐使用命名初始化,这样在扩充结构字段或调整字段顺序时,不会导致语句初始化错误. package main import "fmt" func main() { u := struct { //直接定义匿名结构变量 name string age int8 }{ name: "kebi", age: 18, } type file struct { name string attr struct { //定义匿名结构类型字段 owner int perm int } } f := file{ name: "test.py", // attr: { //missing type in composite literal,对于结构体中的结构体赋值方式有所不同 // owner: 10, // perm: 755, // }, } f.attr.owner = 10 //正确方式 f.attr.perm = 755 fmt.Println(u, f) //{kebi 18} {test.py {10 755}} }
只有在所有字段类型全部支持时,才可做相等操作。 package main import "fmt" func main() { type data struct { x int y map[string]int //字典类型不支持==, } d1 := data{ x: 100, } d2 := data{ x: 100, } fmt.Println(d1 == d2) //struct containing map[string]int cannot be compared }
可使用指针直接操作结构字段,但不能是多级指针。 package main import "fmt" func main() { type user struct { name string age int } p := &user{ //获取指针 name: "kebi", age: 26, } p.name = "maoxian" //通过指针找到对应的程序实体 p.age++ fmt.Println(p) //&{maoxian 27} p2 := &p //&p属于二级指针 *p2.name = "xiaoniao" //p2.name undefined (type **user has no field or method name) }
空结构 空结构struct{}是指没有字段的结构类型。 package main import ( "fmt" "unsafe" ) func main() { var a struct{} //匿名结构体 var b [100]struct{} //以结构体作为元素类型的数组 fmt.Println(unsafe.Sizeof(a), unsafe.Sizeof(b)) //0 0 s := b[:] b[1] = struct{}{} //重新赋值 s[2] = struct{}{} fmt.Println(s[3], len(s), cap(s)) //{} 100 100 }
实际上,这类长度为0的对象通常指向runtime.zerobase变量。 package main import "fmt" func main() { a := [10]struct{}{} b := a[:] c := [0]int{} fmt.Printf("%p, %p, %p\n", &a[0], &b[0], &c) //0x5771c8, 0x5771c8, 0x5771c8 }
空结构可作为通道元素类型,用于事件通知。 package main import "fmt" func main() { exit := make(chan struct{}) go func() { fmt.Println("hello, world!") exit <- struct{}{} }() <-exit fmt.Println("end.") }
匿名字段 package main import "fmt" type attr struct { perm int } type file struct { name string attr //仅有类型名 } func main() { f := file{ name: "test.dat", attr: attr{ //将类型名当作字段名 perm: 755, }, } f.perm = 500 //直接设置匿名字段成员 fmt.Println(f, f.perm) //直接读取匿名字段成员 }
如果嵌入其它包中的类型,则隐式字段名称不包括包名。 package main import "fmt" type data struct { *int //嵌入指针类型 string } func main() { x := 100 d := data{ int: &x, //使用基础类型作为字段名 string: "abc", } fmt.Printf("%#v\n", d) } /* main.data{ int:(*int)(0xc00000a168), string:"abc" } */ 不能将基础类型和其指针类型同时嵌入,因为两者隐式名字相同,下面就是错误示例。 // type data struct { // *int // int // }
虽然可以像普通字段那样访问匿名字段成员,但会存在重名问题。 package main import "fmt" type file struct { name string } type data struct { file name string //与匿名字段file.name重名 } func main() { d := data{ name: "data", file: file{"file"}, //这种方式赋值并没有影响 } fmt.Println(d.name, d.file.name) //data file d.name = "data2" d.file.name = "file2" fmt.Println(d.name, d.file.name) //data2 file2 }
如果多个相同层级的匿名字段成员重名,就只能使用显式字段名访问,因为编译器无法确定目标。 package main import "fmt" type file struct { name string } type log struct { name string } type data struct { file //file和log层次相同 log //file.name和log.name重名 } func main() { d := data{ file: file{"1.txt"}, log: log{"test.log"}, } fmt.Println(d) //{{1.txt} {test.log}} d2 := data{} // d2.name = "name" //ambiguous selector d2.name d2.file.name = "file" //显式命名字段 d2.log.name = "log" fmt.Println(d2) //{{file} {log}} }
严格说来,Go并不是传统意义上的面向对象编程语言,或者说仅实现了最小面向对象的机制。
字段标签(tag)并不是注释,而是用来对字段进行描述的元数据。 package main import ( "fmt" "reflect" ) type user struct { name string `昵称` sex int `性别` } func main() { u := user{"Tom", 1} v := reflect.ValueOf(u) t := v.Type() for i, n := 0, t.NumField(); i < n; i++ { fmt.Printf("%s: %v\n", t.Field(i).Tag, v.Field(i)) } } /* 昵称: Tom 性别: 1 */
|
请发表评论