Go 语言结构(Struct)详解
在 Go 语言中,struct(结构体)是一种复合数据类型,用于将多个不同类型的数据组合在一起。它类似于 C 语言中的 struct 或 Java 中的 class(但 Go 语言没有类的概念)。
1. 结构体的定义
Go 语言使用 type 关键字定义结构体,struct 关键字用于声明结构体类型。例如:
package main
import "fmt"
// 定义一个结构体
type Person struct {
Name string
Age int
Address string
}
func main() {
// 创建结构体实例
p := Person{"Alice", 25, "Beijing"}
fmt.Println(p)
}
输出:
{Alice 25 Beijing}
2. 结构体的初始化
Go 语言支持多种方式初始化结构体实例。
(1)使用字面量初始化
p1 := Person{"Bob", 30, "Shanghai"} // 顺序匹配字段
p2 := Person{Name: "Tom", Age: 28} // 使用字段名初始化(部分字段)
(2)使用 new 关键字
p3 := new(Person) // 返回指针 *Person,字段默认值
p3.Name = "Mike"
p3.Age = 22
(3)使用 & 直接创建指针
p4 := &Person{"Emma", 26, "Guangzhou"} // 直接返回指针
3. 结构体字段
(1)匿名字段
Go 允许定义没有字段名称的结构体(匿名字段),该字段的类型即为名称。
type User struct {
string
int
}
u := User{"John", 25}
fmt.Println(u.string, u.int) // 访问方式
(2)嵌套结构体
结构体可以嵌套另一个结构体:
type Address struct {
City string
State string
}
type Employee struct {
Name string
Age int
Address // 匿名嵌套
}
e := Employee{"Jack", 35, Address{"New York", "NY"}}
fmt.Println(e.City) // 直接访问 Address 的字段
4. 结构体的方法
Go 允许在结构体上定义方法(方法是带有接收者的函数)。
type Rectangle struct {
Width, Height float64
}
// 定义方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
rect := Rectangle{10, 5}
fmt.Println(rect.Area()) // 50
(1)指针接收者
使用指针接收者可以修改结构体内部值:
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
这样 Scale 方法可以修改 Rectangle 实例的 Width 和 Height。
5. 结构体的 JSON 处理
Go 语言的 encoding/json 包允许结构体与 JSON 互转。
package main
import (
"encoding/json"
"fmt"
)
type Product struct {
Name string `json:"name"`
Price float64 `json:"price"`
}
func main() {
p := Product{"Laptop", 1299.99}
jsonData, _ := json.Marshal(p)
fmt.Println(string(jsonData)) // {"name":"Laptop","price":1299.99}
}
(1)JSON 反序列化
var p2 Product
json.Unmarshal(jsonData, &p2)
fmt.Println(p2.Name, p2.Price)
6. 结构体的比较
结构体可以直接比较(所有字段可比较):
p1 := Person{"Alice", 25, "Beijing"}
p2 := Person{"Alice", 25, "Beijing"}
fmt.Println(p1 == p2) // true
7. 结构体与接口
Go 语言的接口可以用于结构体,实现多态特性:
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func main() {
var s Shape = Circle{10}
fmt.Println(s.Area()) // 314
}
8. 结构体标签(Struct Tags)
结构体字段可以使用标签(Tag)存储额外信息(常用于 JSON 解析、数据库 ORM)。
type User struct {
ID int `json:"id"`
Name string `json:"name,omitempty"`
}
json:"name,omitempty"表示如果Name为空,则 JSON 中不显示该字段。
9. 结构体与内存布局
结构体的字段会按照声明顺序排列,Go 会进行内存对齐优化:
type A struct {
a int8 // 1 字节
b int64 // 8 字节
c int8 // 1 字节
}
为了减少内存占用,可以调整字段顺序:
type B struct {
a int8 // 1 字节
c int8 // 1 字节
b int64 // 8 字节
}
10. 参考资料
- 官方文档:Go Struct
- JSON 序列化:Go encoding/json
- Go 语言接口:Go Interfaces