#Struct 类型 - Struct Types
结构体是 Go 语言聚合不同类型数据的方式。
#结构体基础
#定义结构体
// 定义结构体类型
type User struct {
ID int
Name string
Email string
}
// 创建结构体实例
u1 := User{1, "Alice", "alice@example.com"}
fmt.Println(u1) // {1 Alice alice@example.com}
// 指定字段名初始化
u2 := User{
ID: 2,
Name: "Bob",
}
fmt.Println(u2) // {2 Bob }#访问字段
u := User{ID: 1, Name: "Alice"}
// 读取字段
fmt.Println(u.Name) // Alice
// 修改字段
u.Name = "Bob"
fmt.Println(u.Name) // Bob#结构体标签
#使用标签
type User struct {
ID int `json:"id" db:"user_id"`
Name string `json:"name" db:"name"`
Password string `json:"-" db:"password"` // json:"-" 表示不序列化
}
// 通过反射获取标签
import "reflect"
t := reflect.TypeOf(User{})
field, _ := t.FieldByName("ID")
fmt.Println(field.Tag.Get("json")) // id
fmt.Println(field.Tag.Get("db")) // user_idjson:"field_name"- JSON 序列化db:"column_name"- 数据库字段xml:"element"- XML 序列化form:"field"- 表单字段
#匿名字段(嵌入)
#结构体嵌入
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address // 匿名嵌入
}
p := Person{
Name: "Alice",
Address: Address{
City: "Beijing",
Country: "China",
},
}
// 可以直接访问嵌入字段的字段
fmt.Println(p.City) // Beijing(提升字段)
fmt.Println(p.Address.City) // Beijing(完整路径)#嵌入提升
type Animal struct {
Name string
}
func (a Animal) Speak() string {
return "..."
}
type Dog struct {
Animal // 匿名嵌入
Breed string
}
d := Dog{
Animal: Animal{Name: "Buddy"},
Breed: "Golden Retriever",
}
fmt.Println(d.Name) // Buddy(提升字段)
fmt.Println(d.Speak()) // ...(提升方法)#结构体比较
type Point struct {
X, Y int
}
p1 := Point{1, 2}
p2 := Point{1, 2}
p3 := Point{1, 3}
fmt.Println(p1 == p2) // true
fmt.Println(p1 == p3) // false可比较条件 只有所有字段都可比较的结构体才能比较:
type User struct {
Name string
Data []int // 不可比较
}
// u1 == u2 // 编译错误:结构体包含不可比较字段#结构体是值类型
type Point struct {
X, Y int
}
p1 := Point{1, 2}
p2 := p1 // 拷贝整个结构体
p2.X = 10
fmt.Println(p1) // {1 2} - 原结构体不受影响
fmt.Println(p2) // {10 2}#使用指针避免拷贝
// 对于大结构体,使用指针
func process(u *User) {
u.Name = "Processed"
}
u := &User{ID: 1, Name: "Alice"}
process(u)
fmt.Println(u.Name) // Processed#构造函数
Go 没有内置构造函数,通常使用 New 开头的函数:
type User struct {
ID int
Name string
}
// 构造函数
func NewUser(id int, name string) *User {
return &User{
ID: id,
Name: name,
}
}
// 使用
u := NewUser(1, "Alice")
fmt.Println(u.Name) // Alice#结构体布局
#内存对齐
type BadStruct struct {
A bool // 1 字节
B int64 // 8 字节
C bool // 1 字节
// 实际占用:24 字节(因为对齐)
}
type GoodStruct struct {
B int64 // 8 字节
A bool // 1 字节
C bool // 1 字节
// 实际占用:16 字节
}
import "unsafe"
fmt.Println(unsafe.Sizeof(BadStruct{})) // 16
fmt.Println(unsafe.Sizeof(GoodStruct{})) // 16优化建议 将相同大小的字段放在一起,减少内存填充。
#常用模式
#Builder 模式
type Server struct {
host string
port int
timeout time.Duration
}
type ServerOption func(*Server)
func WithHost(host string) ServerOption {
return func(s *Server) {
s.host = host
}
}
func WithPort(port int) ServerOption {
return func(s *Server) {
s.port = port
}
}
func NewServer(opts ...ServerOption) *Server {
s := &Server{
host: "localhost",
port: 8080,
timeout: 30 * time.Second,
}
for _, opt := range opts {
opt(s)
}
return s
}
// 使用
server := NewServer(
WithHost("example.com"),
WithPort(443),
)#链式调用
链式调用让方法返回结构体指针,实现流畅的 API:
type Builder struct {
name string
age int
city string
}
// 每个方法都返回 *Builder,支持链式调用
func (b *Builder) SetName(name string) *Builder {
b.name = name
return b
}
func (b *Builder) SetAge(age int) *Builder {
b.age = age
return b
}
func (b *Builder) SetCity(city string) *Builder {
b.city = city
return b
}
func (b *Builder) Build() *Builder {
return b
}
// 使用链式调用
builder := &Builder{}
result := builder.
SetName("Alice").
SetAge(25).
SetCity("Beijing").
Build()
fmt.Println(result) // &{Alice 25 Beijing}- 方法使用指针接收者
*Builder - 每个方法返回指针
return b - 每行以点结尾,方便链式书写
#实际应用:HTTP 请求构建器
type Request struct {
url string
method string
headers map[string]string
body []byte
}
type RequestBuilder struct {
request *Request
}
func NewRequestBuilder(url string) *RequestBuilder {
return &RequestBuilder{
request: &Request{
url: url,
method: "GET",
headers: make(map[string]string),
},
}
}
func (rb *RequestBuilder) Method(method string) *RequestBuilder {
rb.request.method = method
return rb
}
func (rb *RequestBuilder) Header(key, value string) *RequestBuilder {
rb.request.headers[key] = value
return rb
}
func (rb *RequestBuilder) Body(body []byte) *RequestBuilder {
rb.request.body = body
return rb
}
func (rb *RequestBuilder) Build() *Request {
return rb.request
}
// 使用
req := NewRequestBuilder("https://api.example.com").
Method("POST").
Header("Content-Type", "application/json").
Body([]byte(`{"name":"Alice"}`)).
Build()#练习
- 定义 Rectangle 结构体,计算面积和周长
- 实现 Point 结构体的 String() 方法
- 创建配置结构体,支持链式设置

