嵌套结构体
一个结构体中的字段可以是另一个结构体类型的变量,这就缔造了嵌套形式的结构体类型
- type superhero struct {
name string
age int
addr address
} - type address struct {
city string
street string
number int
访问内嵌结构体的字段,依然是使用"."语法。
s := superhero{ ... }
fmt.Println(s.addr.city, s.addr.street, s.addr.number)
// 结构体中某个字段的数据类型可以又是结构体,由此构成多层级的结构体嵌套
package main
import "fmt"
type superhero struct {
name string
age int
addr address
}
type address struct {
city string
street string
number int
}
func main() {
s := superhero{
name: "Batman",
age: 32,
addr: address{
city: "Gotham",
street: "Mountain Drive",
number: 1007,
},
}
fmt.Printf("%#v\n", s) // #v输出类型信息
// main.superhero{name:"Batman", age:32, addr:main.address{city:"Got
// ham", street:"Mountain Drive", number:1007}}
fmt.Println(s.name, s.age, s.addr.city,
s.addr.street, s.addr.number)
// Batman 32 Gotham Mountain Drive 1007
}
自定义默认值
在不为结构体变量中的各个字段显式指定初值的情况下,编译器会自动将其初始化为适当类型的零值。
类型 | 零值 | |
数值型 | 整型 | 0 |
浮点型 | 0.0 | |
逻辑型 | 布尔型 | false |
容器型 | 字符串 | "" |
切片 | [] | |
映射 | {} | |
引用型 | 指针 | nil |
函数 | nil | |
接口 | nil | |
通道 | nil |
Go语言没有提供为变量设置自定义默认值的内置方法,但可以通过定义构造函数来间接地达到类似的效果。构造函数负责创建包括结构体在内的特定类型的变量,并在没有显式提供构造参数的情况下将其设置为自定义的默认值。
- type alarm struct { ... }
- func newAlarm(time string) alarm {
a := alarm{time: time, sound: "Klaxon" /* 自定义默认值 */}
return a
} - a := newAlarm("7:00")
通过构造函数设置自定义默认值,只是一种语法技巧,而非Go语言规范的一部分。
// Go语言没有提供自定义结构体字段默认值的内置方法,但可以通过构造函数为结构体
// 的全部或部分字段提供默认值
package main
import "fmt"
type alarm struct {
time string
sound string
}
func newAlarm(time string) alarm {
a := alarm{time: time, sound: "Klaxon" /* 自定义默认值 */}
return a
}
func main() {
a := newAlarm("7:00")
fmt.Printf("%+v\n", a) // {time:7:00 sound:Klaxon}
}
比较结构体(3种方法)
结构体变量之间可以进行比较,但仅限于相等(==)和不等(!=)的判断,没有包含、大小于的比较。
只有当两个结构体变量对应字段的值都相等时它们才相等(顺序也在对应性的要求内),只要有一个字段不等,这两个结构体变量就不等。
只有同一种结构体类型的变量之间才能进行比较,否则将导致编译错误。(即使结构体的每一个字段的名称、字段值、顺序都相等,但结构体名字不同,也无法比较,其被视为不同的结构体)。
要检查结构体变量的类型,可选择以下三种方法中的任意一种:
- fmt.Printf("%#v\n", a)
- main.drink{name:"", ice:false}
- fmt.Printf("%T\n", a)(首次出现)
- main.drink
- fmt.Println(reflect.TypeOf(a))
- main.drink
// 比较结构体变量的类型
// 类型相同的结构变量,可以通过“==”和“!=”,做相等性和不等性的比较
package main
import "fmt"
type drink struct {
name string
ice bool
}
func main() {
a := drink{name: "Lemonade", ice: true}
b := drink{name: "Lemonade", ice: true}
c := drink{name: "Orangeade", ice: true}
d := drink{name: "Lemonade", ice: false}
e := drink{name: "Orangeade", ice: false}
fmt.Println(a == b, a != b) // true false
fmt.Println(a == c, a != c) // false true
fmt.Println(a == d, a != d) // false true
fmt.Println(a == e, a != e) // false true
}
// 检查结构体变量的类型
// 借助反射查看结构体变量的类型
package main
import (
"fmt"
"reflect"
)
type drink struct {
name string
ice bool
}
func main() {
a := drink{}
fmt.Printf("%#v\n", a) //main.drink{name:"", ice:false}
fmt.Printf("%T\n", a) // main.drink
fmt.Println(reflect.TypeOf(a)) // main.drink
}