Golang的结构体是用户自定义的数据类型,用于将多个不同类型的字段组合成一个整体,在Go语言的项目开发中应用非常广泛,比如定义业务实体、配置参数结构等场景都会用到结构体。
Golang结构体的定义方式
定义Golang结构体需要使用type关键字和struct关键字,基本语法格式如下:
// 定义名为Person的结构体
type Person struct {
// 字段名 字段类型
Name string // 姓名
Age int // 年龄
city string // 所在城市,小写开头字段
}
结构体定义时需要注意几个要点:
- 结构体名称一般遵循大驼峰命名法,首字母大写的结构体可以被其他包访问,首字母小写的只能在当前包内使用
- 字段名同样遵循命名规则,首字母大写的字段是导出字段,可以被其他包访问,首字母小写的字段是未导出字段,仅当前包可用
- 字段类型可以是Go语言的基础类型,也可以是其他结构体、切片、映射等复合类型
Golang结构体字段的访问规则
结构体字段的访问权限由字段名的首字母大小写决定,同时访问方式也会根据结构体实例的类型有所不同,具体规则如下:
1. 导出字段与未导出字段的访问限制
首字母大写的字段属于导出字段,首字母小写的属于未导出字段,这是Go语言的访问控制核心规则:
package main
import "fmt"
type Student struct {
Name string // 导出字段,可跨包访问
score int // 未导出字段,仅当前包可访问
}
func main() {
s := Student{
Name: "张三",
score: 90, // 当前包内可以访问未导出字段
}
fmt.Println(s.Name) // 可以正常访问导出字段
fmt.Println(s.score) // 当前包内可以访问未导出字段
}
如果上述Student结构体定义在mypackage包中,那么在main包中导入mypackage后,只能访问Name字段,无法直接访问score字段,否则会编译报错。
2. 结构体实例的字段访问方式
结构体实例创建后,访问字段需要使用点号.操作符,不同实例类型的访问方式如下:
普通结构体实例访问
func main() {
// 方式1:声明后逐个赋值
var p Person
p.Name = "李四"
p.Age = 25
// p.city = "北京" // 当前包内可访问,跨包不可访问
// 方式2:初始化时直接赋值
p2 := Person{
Name: "王五",
Age: 30,
city: "上海",
}
fmt.Println(p2.Name, p2.Age)
}
结构体指针实例访问
Go语言中结构体指针访问字段时,不需要手动解引用,直接使用点号即可:
func main() {
p := &Person{
Name: "赵六",
Age: 28,
}
// 以下两种访问方式等价
fmt.Println(p.Name) // 直接通过指针访问字段,Go自动解引用
fmt.Println((*p).Name) // 手动解引用后访问,效果相同
}
3. 嵌套结构体的字段访问规则
当一个结构体包含另一个结构体作为字段时,属于嵌套结构体,访问内部结构体字段有两种方式:
// 定义地址结构体
type Address struct {
Province string
City string
}
// 定义用户结构体,嵌套Address结构体
type User struct {
Name string
Age int
Address // 匿名字段,嵌套的结构体类型名作为字段名
}
func main() {
u := User{
Name: "孙七",
Age: 32,
Address: Address{
Province: "广东",
City: "深圳",
},
}
// 方式1:直接访问匿名字段的内部字段,Go会自动向上查找
fmt.Println(u.Province, u.City)
// 方式2:通过嵌套的结构体字段名访问
fmt.Println(u.Address.Province, u.Address.City)
}
如果嵌套的是有名结构体字段,那么必须通过字段名才能访问内部字段,不能直接省略中间层级。
常见注意事项
- 结构体定义时如果字段类型是指针、切片、映射等引用类型,初始化时默认值是
nil,直接使用可能会触发空指针异常,需要先初始化再操作 - 未导出字段虽然不能直接跨包访问,但可以通过当前包内提供的导出方法间接修改和获取值
- 结构体作为参数传递时,默认是值拷贝,修改拷贝的实例不会影响原实例,如果需要修改原实例,需要传递结构体指针
Go语言的结构体访问控制规则是语法层面强制实现的,没有其他语言中的public、private等修饰符,仅通过字段名首字母大小写控制,这是Go语言简洁设计理念的体现。