1. 相邻的同类型字段可以声明在一起
struct {
title string
author string
pages int
}
//上边的无名结构体可以写成下边这样:
struct {
title, author string
pages int
}
2. 一个结构体类型的尺寸为它的所有字段的(类型)尺寸之和加上一些填充字节的数目
常常地,编译器(和运行时)会在一个结构体值的两个相邻字段之间填充一些字节来保证一些字段的地址总是某个整数的倍数。
3. 一个零字段结构体的尺寸为零。
func main() {
type EmptyPerson struct{}
p := EmptyPerson{}
size := unsafe.Sizeof(p)
fmt.Println("Person size:", size)//Person size: 0
}
4. 一个结构体类型中的字段标签和字段的声明顺序对此结构体类型的身份识别很重要。
如果两个无名结构体类型的各个对应字段声明都相同(按照它们的出现顺序),则此两个无名结构体类型是等同的。 两个字段声明只有在它们的名称、类型和标签都等同的情况下才相同。
举例1:两个无名结构体,字段名称.类型.标签相同,顺序不同,不相等
举例2:两个无名结构体,字段名称.类型.顺序相同,标签不同,不相等
举例3:两个无名结构体,字段名称.顺序,类型.标签相同,相等
5. 两个声明在不同的代码包中的非导出字段将总被认为是不同的字段。
字段名称.顺序,类型.标签完全相同的结构体,在不同包中,无论字段是否导出,比较后都是不相等
6. 如果一个组合字面量中最后一项和结尾的}处于同一行,则此项后的逗号,是可选的;否则此逗号不可省略
var _ = User {
name: "zhang",
age: 256,
remark: "bu", // 这里行尾的逗号不可省略
}
// 下行}前的逗号可以省略。
var _ = User{author: "zhang", age: 256, remark: "bu",}
7. 结构体不赋值给具体变量则不能被寻址
package main
import "fmt"
func main() {
type Book struct {
Pages int
}
var book = Book{} // 变量值book是可寻址的
p := &book.Pages
*p = 123
fmt.Println(book) // {123}
// 下面这两行编译不通过,因为Book{}没有赋值给具体变量是不可寻址的,
// 继而Book{}.Pages也是不可寻址的。
/*
Book{}.Pages = 123//先赋值
p = &Book{}.Pages // 在取址,然后赋给p
*/
}
//选择器中的属性选择操作符.的优先级比取地址操作符&的优先级要高。所以
p = &Book{}.Pages 等价于 p = &(Book{}.Pages)
8. 两个不同类型的结构体值均为可比较的条件
8.1. 它们的底层类型相同(要考虑字段标签)
8.2. 至少有一个结构体值的类型为无名类型时(换句话说,只有它们可以被隐式转换为对方的类型的时候)才可以互相比较。
8.3. 备注:在比较中,名为空标识符_的字段将被忽略掉;字段顺序也要相同才能比较
9. 结构体和无名结构体的区分
type S0 struct {//S0是有名结构体
y int "foo"
x bool
}
type S2 = struct { // S2是一个无名结构体类型
x int "foo"
y bool
}
//s2 是变量名,而不是结构体类型名。
//虽然我们使用 type 关键字为这个结构体定义了一个类型别名 S2,
//但是这并不意味着这个结构体本身有一个名字。