跳转到主要内容
模块 5 · 第 1 课(共 5)课程中的21/50~12 min
模块课程(1/5)

定义和使用结构体

struct 将命名字段分组为单一类型。这是 Go 的方式 构建“对象”——比类更字面和直接, 没有继承,也没有内置构造函数。

宣言

Go
type Person struct {
    Name string
    Age  int
}

type 引入了新的命名类型。每个字段写入一个 行,name type。相同类型的连续字段可以共享 声明:X, Y int。

创建

Go
// with named fields (recommended: robust to reordering)
p := Person{Name: "Ada", Age: 36}

// positional (fragile: depends on declaration order)
q := Person{"Ada", 36}

// zero value: every field at its zero value
var r Person          // r = {Name: "", Age: 0}

// pointer: allocate with & or new
ptr := &Person{Name: "Ada"}
ptr2 := new(Person)   // *Person to a zero-value struct

现场访问

Go
p := Person{Name: "Ada", Age: 36}
fmt.Println(p.Name, p.Age)

p.Age = 37            // mutation (if p is a variable)

对于指针,ptr.Name 直接起作用:Go 执行 隐式取消引用。没有像 C 中那样的 -> 。

可见性:大写规则

导出带有大写首字母的字段(从其他字段可见) 包);小写=当前包私有。

Go
type User struct {
    Name   string  // exported
    salt   []byte  // private to the package
}

同样的规则适用于 Go 中的每个标识符:类型、 函数、变量、字段。

匿名和嵌套结构

Go
// anonymous (handy for ad-hoc data)
config := struct {
    Host string
    Port int
}{Host: "localhost", Port: 8080}

// nested
type Address struct {
    Street string
    City   string
}
type Customer struct {
    Name    string
    Address Address
}

可比性

如果两个结构的所有字段都是,则它们与 == 可比较 可比较(内部没有切片/映射/函数):

Go
a := Person{Name: "Ada", Age: 36}
b := Person{Name: "Ada", Age: 36}
fmt.Println(a == b)   // true

这还允许您将它们用作地图键。

尝试一下

锻炼#go.m5.l1.e1
尝试:0加载中...

使用 Name string 和 Age int 定义 Person 类型,然后在 main 中将其实例化为 {Name: 'Ada', Age: 36}。

正在加载编辑器...
显示提示

语法:`类型名称结构{字段类型; ...}`。

3 次尝试后可用的解决方案

锻炼#go.m5.l1.e2
尝试:0加载中...

打印 p(现有人员)的名称字段的值。

正在加载编辑器...
显示提示

字段访问:`p.Field`。

3 次尝试后可用的解决方案

Quiz#go.m5.l1.e3
准备好

另一个包中“名称字符串”字段(小写)的可见性如何?

Go
// in package other
type X struct {
    name string
}
答案选项

回顾

  • type Name struct { ... }:带有命名字段的新命名类型。
  • 构造:T{Field: value, ...}(推荐)或位置。
  • 零值:每个字段的类型为零。
  • &T{...} 和 new(T) 用于指针;隐式取消引用(p.Field 上的 *T)。
  • 大写=导出;小写=包私有。
  • 如果所有字段都是,则结构与 == 相当;可用作地图键。