Go 语言结构体

定义、字面量、嵌入(组合)、标签、以及结构体比较。

Beginner
Key PointsGo 用结构体 + 嵌入实现组合,没有继承;嵌入的方法会被「提升」到外层。

定义与使用

Go
type User struct {
	ID    int
	Name  string
	Email string
	Age   int
}

u := User{ID: 1, Name: "张三", Age: 20}
fmt.Println(u)
fmt.Println(u.Name)
fmt.Printf("%+v\n", u)          // 带字段名
Output
{1 张三  20}
张三
{ID:1 Name:张三 Email: Age:20}

指针与零值

Go
var u User                      // 所有字段都是零值
fmt.Printf("%+v\n", u)

p := &User{Name: "李四"}        // 指针,字段自动解引用
p.Age = 30
fmt.Println(p.Age, p.Name)
Output
{ID:0 Name: Email: Age:0}
30 李四

嵌入(组合)

Go
type Base struct {
	ID        int
	CreatedAt string
}

func (b Base) Describe() string {
	return fmt.Sprintf("ID=%d", b.ID)
}

type Article struct {
	Base                    // 嵌入,字段和方法被提升
	Title string
}

a := Article{Base: Base{ID: 7}, Title: "Go 入门"}
fmt.Println(a.ID)               // 提升字段
fmt.Println(a.Describe())       // 提升方法
Output
7
ID=7

Embedding is not inheritance: Article has a Base, it is not a Base. You cannot assign an Article to a Base variable, and embedding gives no polymorphism — that is what interfaces are for.

方法

Go
func (u User) Full() string {
	return u.Name + " <" + u.Email + ">"
}

func (u *User) SetName(n string) {
	u.Name = n
}

u := User{Name: "张三", Email: "z@example.com"}
u.SetName("张三丰")             // 编译器自动取地址
fmt.Println(u.Full())
Output
张三丰 <z@example.com>

标签

Go
type Login struct {
	User string `json:"user" form:"user" validate:"required"`
	Pwd  string `json:"-"`            // 序列化时忽略
}

b, _ := json.Marshal(Login{User: "tom", Pwd: "secret"})
fmt.Println(string(b))
Output
{"user":"tom"}

Tags are string metadata read via reflection. json, yaml, db and validate all depend on them. A typo compiles fine and fails silently at runtime — the kind of bug that eats an afternoon.

比较

Go
a := User{ID: 1, Name: "x"}
b := User{ID: 1, Name: "x"}
fmt.Println(a == b)              // 所有字段都可比较时才能 ==

// 含 slice / map / func 字段的结构体不能比较
type Bad struct{ Tags []string }
// fmt.Println(Bad{} == Bad{})   // 编译错误
Output
true
Structs with []T, map or func fields cannot use == or be map keys. Use reflect.DeepEqual or write an Equal method (faster and clearer).

Friends & Partners