struct(结构体)也是一种聚合的数据类型,struct可以包含多个任意类型的值,这些值被称为struct的字段。用来演示struct的一个经典案例就是雇员信息,每条雇员信息包含:员工编号,姓名,住址,出生日期,工作岗位,薪资,直属领导等。每个雇员的所有信息都可以存在一个struct中,该struct可以作为变量,或者作为函数的参数、返回值,或者被存到数组、切片中,等等。
下面声明了一个Employee类型的结构体,还声明了一个Employee类型的变量dilbert:
type Employee struct {
ID int
Name string
Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
var dilbert Employee
dilbert的struct字段可以通过点操作符来访问,例如dilbert.Name和dilbert.Dob。同时dilbert的字段是变量,因此可以直接对成员赋值:
dilbert.Salary -= 5000 // demoted, for writing too few lines of code
也可以对成员进行取址,然后通过指针访问:
position := &dilbert.Position
*position = "Senior " + *position // promoted, for outsourcing to Elbonia
点操作符还可以应用在struct指针上:
var employeeOfTheMonth *Employee = &dilbert
employeeOfTheMonth.Position += " (proactive team player)"
上面的第二条语句相当于:
(*employeeOfTheMonth).Position += " (proactive team player)"
EmployeeByID函数根据给定的员工编号返回一个指针指向包含员工信息的struct,可以使用点操作符来访问里面的字段:
func EmployeeByID(id int) *Employee { /* ... */ }
fmt.Println(EmployeeByID(dilbert.ManagerID).Position) // "Pointy-haired boss"
id := dilbert.ID
EmployeeByID(id).Salary = 0 // fired for... no real reason
最后那条语句要注意,它调用EmployeeByID生成了一个*Employee指针,然后直接更新该结构体中的一个字段。如果将EmployeeByID的返回值从*Employee换成Employee类型,那么编译将报错,因为编译器无法对返回的Employee进行寻址(不通过变量直接使用一个值,一般都无法进行寻址)。
struct声明时,通常是一行写一个字段,字段名在类型之前,不过如果两个字段类型相同,那么可以合并到一行,例如Name和Address:
type Employee struct {
ID int
Name, Address string
DoB time.Time
Position string
Salary int
ManagerID int
}
对于struct类型来说,字段的先后顺序是非常关键的。如果两个struct类型包含了完全相同的字段,但是排列顺序不同或者进行了部分合并,那么这两个struct就是不同的类型!