Go 语言中结构体(struct)是自定义复合类型,用来将多个不同类型的字段(变量)组合在一起,描述一个事物的属性,相当于其他语言的「类」,但 Go 没有类,结构体是实现面向对象编程的核心。
一、基础定义与声明
1. 定义结构体
使用 type + struct 关键字定义:
// 语法
type 结构体名 struct {
字段名 字段类型
字段名 字段类型
// ...
}
示例:定义一个「人」的结构体
// 定义 Person 结构体
type Person struct {
Name string // 姓名
Age int // 年龄
City string // 城市
}
2. 创建结构体实例(赋值)
有 4 种常用方式:
package main
import "fmt"
type Person struct {
Name string
Age int
City string
}
func main() {
// 方式1:按字段顺序赋值(必须严格对应)
p1 := Person{"张三", 20, "北京"}
// 方式2:指定字段名赋值(推荐,顺序无关)
p2 := Person{Name: "李四", Age: 25}
// 方式3:先声明,后赋值
var p3 Person
p3.Name = "王五"
p3.Age = 30
p3.City = "上海"
// 方式4:指针方式创建(推荐用于大结构体,节省内存)
p4 := Person{Name: "赵六", Age: 35, City: "深圳"}
// 打印结果
fmt.Println(p1, p2, p3, p4)
}

3. 访问结构体字段
直接使用 . 访问:
// 普通实例
fmt.Println(p1.Name) // 输出:张三
p1.Age = 21 // 修改字段
// 指针实例(Go 自动解引用,无需写 *)
fmt.Println(p4.City) // 输出:深圳
二、结构体进阶用法
1. 结构体嵌套(组合)
结构体可以嵌套其他结构体,实现「属性包含」:
// 地址结构体
type Address struct {
Province string
Street string
}
// 用户结构体(嵌套 Address)
type User struct {
ID int
Username string
Addr Address // 嵌套结构体
}
// 使用
u := User{
ID: 1,
Username: "admin",
Addr: Address{
Province: "广东",
Street: "科技园路",
},
}
// 访问嵌套字段
fmt.Println(u.Addr.Province) // 输出:广东
2. 匿名嵌套(简化访问)
省略字段名,直接嵌套结构体类型,可以直接访问嵌套字段:
type User struct {
ID int
Username string
Address // 匿名嵌套
}
// 使用
u := User{
ID: 1,
Username: "admin",
Address: Address{Province: "广东", Street: "科技园路"},
}
// 直接访问匿名嵌套字段(简化写法)
fmt.Println(u.Province) // 直接访问,无需 u.Address.Province
3. 结构体方法(给结构体绑定函数)
这是 Go 实现「面向对象」的核心,给结构体定义专属函数(方法):
// 语法:func (接收者 结构体类型) 方法名() 返回值 {}
// 给 Person 定义一个打招呼的方法
func (p Person) SayHello() {
fmt.Printf("大家好,我是 %s,今年 %d 岁\n", p.Name, p.Age)
}
// 定义修改年龄的方法(必须用指针接收者,否则修改的是副本)
func (p *Person) GrowUp() {
p.Age++
}
// 使用
p := Person{Name: "张三", Age: 20}
p.SayHello() // 输出:大家好,我是 张三,今年 20 岁
p.GrowUp() // 年龄+1
fmt.Println(p.Age) // 输出:21
接收者两种类型区别
表格
| 接收者类型 | 用法 | 适用场景 |
|---|---|---|
值接收者 (p Person) |
不修改原结构体,只读操作 | 获取数据、打印、计算 |
指针接收者 (p *Person) |
可修改原结构体,节省内存 | 修改字段、大结构体避免拷贝 |
4. 结构体标签(Tag)
结构体字段后加反引号 key:"value",用于序列化、数据库映射、校验等(最常用在 JSON 转换):
type User struct {
ID int `json:"user_id" db:"id"` // JSON 字段名改为 user_id
Username string `json:"username" db:"name"` // 数据库映射为 name
Age int `json:"age,omitempty"` // 为空时忽略该字段
}
三、零值与初始化
- 结构体未赋值时,所有字段为对应类型零值(字符串空、数字 0、指针 nil)
- 可以使用
new()初始化,返回指针:
四、结构体比较
- 相同结构体类型 可以直接用
==比较(所有字段都相等则结构体相等) - 包含切片、map 等不可比较类型的结构体,不能用
==比较
五、完整实战示例
package main
import "encoding/json"
import "fmt"
// 定义结构体 + 标签
type Student struct {
ID int `json:"id"`
Name string `json:"name"`
Score float64`json:"score"`
}
// 结构体方法:获取成绩等级
func (s Student) GetLevel() string {
if s.Score >= 90 {
return "A"
} else if s.Score >= 60 {
return "B"
}
return "C"
}
func main() {
// 1. 创建实例
stu := Student{ID: 1, Name: "小明", Score: 95.5}
// 2. 调用方法
fmt.Println("成绩等级:", stu.GetLevel()) // A
// 3. 结构体转 JSON
jsonData, _ := json.Marshal(stu)
fmt.Println("JSON:", string(jsonData))
// 输出:{"id":1,"name":"小明","score":95.5}
}

总结
- 结构体是 Go 的复合类型,用于封装多个不同类型字段,描述事物属性
- 核心用法:定义结构体 → 创建实例 → 访问字段 → 绑定方法
- 指针接收者用于修改结构体 ,值接收者用于只读操作
- 标签(Tag)常用于 JSON、数据库等场景的字段映射
- 结构体是 Go 面向对象编程的基础,替代了其他语言的「类」