结构体类型的字面量由关键字type、类型名称、关键字struct,以及由花括号包裹的若干字段声明组成。
type Person struct {
Name string
Gender string
Age uint8
}
Person{Name: "Robert", Gender: "Male", Age: 33}
键值对的顺序与其类型中的字段声明完全相同的话,我们还可以统一省略掉所有字段的名称
Person{"Robert", "Male", 33}
结构体类型的值字面量时可以只对它的部分字段赋值,甚至不对它的任何字段赋值。
这时,未被显式赋值的字段的值则为其类型的零值。
上述情况下,字段的名称是不能被省略的。
匿名结构体
编写一个结构体值的字面量时不需要先拟好其类型。这样的结构体字面量被称为匿名结构体。
与匿名函数类似,我们在编写匿名结构体的时候需要先写明其类型特征(包含若干字段声明),再写出它的值初始化部分。
p := struct {
Name string
Gender string
Age uint8
}{"Robert", "Male", 33}
匿名结构体最大的用处就是在内部临时创建一个结构以封装数据,而不必正式为其声明相关规则。
而在涉及到对外的场景中,我强烈建议使用正式的结构体类型。
结构体类型可以拥有若干方法(注意,匿名结构体是不可能拥有方法的)
所谓方法,其实就是一种特殊的函数。它可以依附于某个自定义类型。
方法的特殊在于它的声明包含了一个接收者声明。
这里的接收者指代它所依附的那个类型。名为Grow的方法的声明:
func (person *Person) Grow() {
person.Age++
}
p := Person{"Robert", "Male", 33}
p.Grow()
最后,结构体类型属于值类型。
它的零值并不是nil,而是其中字段的值均为相应类型的零值的值。
结构体类型Person的零值若用字面量来表示的话则为Person{}。
package main
import (
"fmt"
)
type Persion struct {
name string
age int
sex byte
}
type Student struct {
Persion //结构体匿名字段,只有类型,没有名字,匿名字段,继承了Persion的成员
int //基础类匿名字段
id int
addr string
name string
}
func main() {
//直接定义一个对象
var xx Student
xx.name = "xiao x"
//结构体中的其他结构体同名字成员变量, 需显示的调用赋值
xx.Persion.name = "xiao xie"
xx.age = 100
fmt.Println(xx)
//顺序初始化,匿名变量的初始化
var xiaoming Student = Student{Persion{"xiaoming", 20, 'm'}, 1, 100, "201 Room", "xx"}
fmt.Println(xiaoming)
//可直接使用匿名对象的类型
fmt.Println(xiaoming.int)
//自动推导
xiaofang := Student{Persion{"xiaofang", 18, 'f'}, 1, 100, "401 Room", "xx"}
fmt.Println(xiaofang)
//指定成员初始化
s3 := Student{Persion: Persion{"xiaofang", 18, 'm'}}
fmt.Println(s3)
s4 := Student{addr: "203 Room"}
fmt.Println(s4)
}
type Student struct {
*Persion //指针类型匿名字段
}
func main() {
//方式1
var xiaoming Student = Student{&Persion{"xiaoming2", 20, 'm'}}
fmt.Println(xiaoming.name)
//方式2
var xiaofang Student
xiaofang.Persion = new(Persion)
xiaofang.Persion.name = "xiaofang"
fmt.Println(xiaofang.Persion.name)
}
//带有接收者的方法叫成员函数
func (p Persion) PrintName() {
fmt.Println(p)
}
//指针接收者
func (p *Persion) setName(str string) {
p.name = str
}
func main() {
var p Persion = Persion{"xiaoming", 10, 'M'}
p.PrintName()
(&p).setName("xiaof")
p.PrintName()
}