结构体基础 #
一、结构体概述 #
结构体是一种聚合数据类型,将多个字段组合成一个整体。
二、结构体定义 #
2.1 基本语法 #
go
type Person struct {
Name string
Age int
City string
}
2.2 字段命名 #
- 首字母大写:公开字段(可导出)
- 首字母小写:私有字段
go
type User struct {
Name string // 公开
email string // 私有
}
2.3 相同类型字段 #
go
type Point struct {
X, Y int
}
2.4 空结构体 #
go
type Empty struct{}
var e Empty
fmt.Println(unsafe.Sizeof(e)) // 0
三、结构体初始化 #
3.1 零值初始化 #
go
var p Person
fmt.Println(p.Name) // ""(零值)
fmt.Println(p.Age) // 0(零值)
3.2 字面量初始化 #
go
p := Person{
Name: "Alice",
Age: 25,
City: "Beijing",
}
3.3 按顺序初始化 #
go
p := Person{"Alice", 25, "Beijing"}
3.4 部分初始化 #
go
p := Person{
Name: "Alice",
Age: 25,
// City为零值
}
3.5 new函数 #
go
p := new(Person)
fmt.Printf("%T\n", p) // *Person
fmt.Println(p.Name) // ""(零值)
四、字段访问 #
4.1 值访问 #
go
p := Person{Name: "Alice", Age: 25}
fmt.Println(p.Name) // Alice
fmt.Println(p.Age) // 25
4.2 指针访问 #
go
p := &Person{Name: "Alice", Age: 25}
fmt.Println(p.Name) // Alice(自动解引用)
fmt.Println((*p).Name) // Alice(显式解引用)
4.3 修改字段 #
go
p := Person{Name: "Alice"}
p.Name = "Bob"
fmt.Println(p.Name) // Bob
五、结构体指针 #
5.1 创建指针 #
go
p := &Person{Name: "Alice"}
// 或
p := new(Person)
p.Name = "Alice"
5.2 函数传递 #
go
func modify(p *Person) {
p.Name = "Modified"
}
func main() {
p := Person{Name: "Alice"}
modify(&p)
fmt.Println(p.Name) // Modified
}
5.3 返回指针 #
go
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
}
}
p := NewPerson("Alice", 25)
六、结构体比较 #
6.1 可比较 #
如果所有字段都可比较,结构体可比较:
go
p1 := Person{Name: "Alice", Age: 25}
p2 := Person{Name: "Alice", Age: 25}
p3 := Person{Name: "Bob", Age: 25}
fmt.Println(p1 == p2) // true
fmt.Println(p1 == p3) // false
6.2 不可比较字段 #
包含切片、映射、函数的结构体不可比较:
go
type Data struct {
Values []int
}
d1 := Data{Values: []int{1, 2, 3}}
d2 := Data{Values: []int{1, 2, 3}}
fmt.Println(d1 == d2) // 编译错误
七、结构体作为字段 #
7.1 命名嵌入 #
go
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address Address
}
p := Person{
Name: "Alice",
Address: Address{
City: "Beijing",
Country: "China",
},
}
fmt.Println(p.Address.City) // Beijing
7.2 匿名嵌入 #
go
type Person struct {
Name string
Address // 匿名嵌入
}
p := Person{
Name: "Alice",
Address: Address{
City: "Beijing",
},
}
fmt.Println(p.City) // Beijing(字段提升)
八、结构体方法 #
8.1 值接收者 #
go
func (p Person) GetName() string {
return p.Name
}
p := Person{Name: "Alice"}
fmt.Println(p.GetName()) // Alice
8.2 指针接收者 #
go
func (p *Person) SetName(name string) {
p.Name = name
}
p := &Person{Name: "Alice"}
p.SetName("Bob")
fmt.Println(p.Name) // Bob
九、工厂函数 #
9.1 构造函数 #
go
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
}
}
p := NewPerson("Alice", 25)
9.2 带验证的构造函数 #
go
func NewPerson(name string, age int) (*Person, error) {
if name == "" {
return nil, errors.New("name cannot be empty")
}
if age < 0 {
return nil, errors.New("age cannot be negative")
}
return &Person{Name: name, Age: age}, nil
}
十、实际应用 #
10.1 配置结构体 #
go
type Config struct {
Host string
Port int
Database string
Timeout time.Duration
}
func NewDefaultConfig() *Config {
return &Config{
Host: "localhost",
Port: 8080,
Database: "mydb",
Timeout: 30 * time.Second,
}
}
10.2 响应结构体 #
go
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
func Success(data interface{}) *Response {
return &Response{
Code: 200,
Message: "success",
Data: data,
}
}
十一、总结 #
结构体要点:
| 特性 | 说明 |
|---|---|
| 定义 | type Name struct |
| 初始化 | 字面量、new函数 |
| 访问 | 点号访问字段 |
| 比较 | 可比较字段可比较 |
| 指针 | 支持指针接收者方法 |
关键点:
- 聚合类型:组合多个字段
- 值类型:赋值和传参复制
- 字段可见性:首字母大小写控制
- 方法:可以为结构体定义方法
- 工厂函数:推荐使用构造函数
准备好学习结构体方法了吗?让我们进入下一章!
最后更新:2026-03-26