🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## struct定义 使用type和struct关键字来定义结构体,具体代码格式如下: ~~~ type 类型名 struct { 字段名 字段类型 字段名 字段类型 … } ~~~ 类型名:标识自定义结构体的名称,在同一个包内不能重复 字段名:表示结构体字段名。结构体中的字段名必须唯一 字段类型:表示结构体字段的具体类型 *说明:同样类型的字段也可以写在一行* ### 结构体字段的可见性 结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问) ### struct实例化 ~~~ stu1 := Student{"jim", 20, 73.5} stu2 := Student{ // 初始化结构体的时候可以简写,也就是初始化的时候不写键,直接写值 name: "Tom", age: 24, weight: 59.3, } stu3 := new(Student) // 注意这里返回的是指针,相当于 stu3 := &Student{} stu3.name = "lisi" ~~~ ## 使用 New() 函数,而非构造器 Go 并不支持构造器。如果某类型的零值不可用,需要程序员来隐藏该类型,避免从其他包直接访问。程序员应该提供一种名为`NewT(parameters)`的[函数](https://studygolang.com/articles/11892),按照要求来初始化`T`类型的变量。按照 Go 的惯例,应该把创建`T`类型变量的函数命名为`NewT(parameters)`。这就类似于构造器了。如果一个包只含有一种类型,按照 Go 的惯例,应该把函数命名为`New(parameters)`, 而不是`NewT(parameters)` ~~~go package employee import ( "fmt" ) type employee struct { firstName string lastName string totalLeaves int leavesTaken int } func New(firstName string, lastName string, totalLeave int, leavesTaken int) employee { e := employee {firstName, lastName, totalLeave, leavesTaken} return e } func (e employee) LeavesRemaining() { fmt.Printf("%s %s has %d leaves remaining", e.firstName, e.lastName, (e.totalLeaves - e.leavesTaken)) } ~~~ ### 结构体的零值(Zero Value) 当定义好的结构体并没有被显式地初始化时,该结构体的字段将默认赋为零值 ### 结构体的指针 创建指向结构体的指针 ~~~go type Employee struct { firstName, lastName string age, salary int } func main() { emp8 := &Employee{"Sam", "Anderson", 55, 6000} fmt.Println("First Name:", (*emp8).firstName) // Go 语言允许我们在访问 firstName 字段时,可以使用 emp8.firstName 来代替显式的解引用 (*emp8).firstName fmt.Println("First Name:", emp8.firstName) fmt.Println("Age:", (*emp8).age) } ~~~ ### 导出结构体和字段 如果结构体名称以大写字母开头,则它是其他包可以访问的导出类型(Exported Type)。同样,如果结构体里的字段首字母大写,它也能被其他包访问到 ~~~go package computer type Spec struct { //exported struct Maker string //exported field model string //unexported field Price int //exported field } ~~~ ### 结构体相等性(Structs Equality) * 结构体是值类型。如果它的每一个字段都是可比较的,则该结构体也是可比较的。如果两个结构体变量的对应字段相等,则这两个变量也是相等的; * 如果结构体包含不可比较的字段,则结构体变量也不可比较 ~~~go type image struct { data map[int]int } func main() { image1 := image{data: map[int]int{ 0: 155, }} image2 := image{data: map[int]int{ 0: 155, }} if image1 == image2 { fmt.Println("image1 and image2 are equal") } } output=> invalid operation: image1 == image2 (struct containing map[int]int cannot be compared) ~~~ ### 结构体内存布局 ~~~ type test struct { a int8 b int8 c int8 d int8 } n := test{ 1, 2, 3, 4, } fmt.Printf("n.a %p\n", &n.a) fmt.Printf("n.b %p\n", &n.b) fmt.Printf("n.c %p\n", &n.c) fmt.Printf("n.d %p\n", &n.d) ~~~ 输出: ~~~ n.a 0xc0000a0060 n.b 0xc0000a0061 n.c 0xc0000a0062 n.d 0xc0000a0063 ~~~