Golang - 结构体
结构体说明
结构体(struct) 是用户自定义的类型,它代表若干字段(基本数据类型/引用数据类型)的集合。有些时候将多个数据看做一个整体要比单独使用这些数据更有意义,这种情况下就适合结构体。
比如将一个员工的name,department,salary三个属性打包在一起成为一个employee结构就很有意义的。
结构体类型
结构体是复合类型(composite types),当声明一个结构体变量的时候,内存空间就已经被分配,每个字段(field)为类型的0值。

上面的内存示意图表明了,变量employee声明为Employee结构体类型的时候,会初始化该结构体中字段类型的0值,然后直接指向声明后的结构体,也可以说明:结构体是值类型。
不同的结构体类型变量字段是独立的,互不影响,一个结构体变量字段的更改,不影响另外一个结构体类型变量。
package main
import "fmt"
type Employee struct {
Name,Department string
Salary float32
Task []string
}
func main() {
var employee1 = Employee{
Name: "易文杰",
Department: "系统开发部",
Salary: 5000,
Task: []string{
"支付",
"客户分配",
},
}
employee2 := employee1
employee2.Name = "张冲"
fmt.Println(employee1,employee2)
}
上面的代码,声明了一个employee1变量后,将employee1赋值给employee2变量,当我们修改employee2的字段Name后,发现emloyee1中的Name并没有被更改。程序的输出结果:
{易文杰 系统开发部 5000 [支付 客户分配]} {张冲 系统开发部 5000 [支付 客户分配]}
结构体的声明
type Employee struct {
Name string
Department string
Salary float32
}
上面的代码声明了一个名为Employee的结构体类型,它拥有Name,Department,Salary三个字段。同一个类型的多个字段可以合并到一行(用逗号进行分隔),并将类型放到后面。上面的结构体中Name和Department都是string的类型,因此可以将它们写到一起。
type Employee struct {
Name,Department string
Salary float32
}
上面结构体Employee是一个具名结构体(named structure),因为它创建了一个具有名称的结构体类型:Employee。我们可以定义具名结构体类型的变量。
我们也可以定义一个没有类型名称的结构体,这种结构体叫做匿名结构体(anonymous structures)
var employee struct{
Name,Department string
Salary float32
}
当结构体中的字段是map,slice,指针的时候,默认的0值是nil(没有分配空间)的时候,需要分配空间后才能被使用
package main
import "fmt"
type Employee struct {
Name,Department string
Salary float32
Mapper map[string]string
Slicer []string
Ptr *int
}
func main() {
var employee Employee
employee.Name = "易文杰"
employee.Department = "系统开发部"
employee.Mapper = make(map[string]string)
employee.Mapper["smile"] = "易文杰"
employee.Slicer = make([]string,10)
employee.Slicer[0] = "切片"
age := 12
employee.Ptr = &age
fmt.Println(employee)
}
当未分配空间就直接使用,会导致代码异常
panic: assignment to entry in nil map
上面的程序会输出:
{易文杰 系统开发部 0 map[smile:易文杰] [切片 ] 0xc00000a098}
结构体的作用域
结构体采用首字母大小写来区分访问权限,当首字母是大写,可以别外包引用。反之,不能。
定义具名结构体变量
下面的程序说明了如何定义一个具名结构体Employee的变量
package main
import "fmt"
//定义结构体
type Employee struct {
Name,Department string
Salary float32
}
func main() {
//使用结构体一
employee1 := Employee{
Name: "易文杰",
Department: "系统研发部",
Salary: 5000,
}
//使用结构体二
employee2 := Employee{"张冲","系统研发部",15000}
fmt.Println(employee1,employee2)
}
在上面的程序中,我们定义了一个名叫Employee的结构体类型,我们可以通过指定字段的名称和对应的值来创建一个结构体变量。其中字段名和类型必须要和结构体中声明的保持一致。
采用第一种定义结构体变量:不需要和声明结构体中的变量顺序保持一致,但最后一个数据需保留,
采用第二种定义结构体变量:需要和声明结构体中的变量顺序保持一致,最后一个数据不需要保留,
上面的程序输出如下:
{易文杰 系统研发部 5000} {张冲 系统研发部 15000}
定义匿名结构体变量
package main
import "fmt"
func main() {
var employee = struct {
Name,Department string
Salary float32
}{"张冲","系统开发部",28000}
fmt.Println(employee)
}
在上面的程序中,我们定义了一个employee匿名结构体变量。这种结构体称为匿名结构体,因为它只创建了一个新的结构体变量employee,而没有定义新的结构体类型。
上面的程序输出为:
{张冲 系统开发部 28000}
访问结构体中的字段
使用.操作符来访问结构体中的字段
package main
import "fmt"
func main() {
var employee = struct {
Name,Department string
Salary float32
}{"张冲","系统开发部",28000}
fmt.Printf("姓名%v\n部门%v\n工资%v\n",employee.Name,employee.Department,employee.Salary)
}
在上面的程序中,通过employee.Name来访问employee中的字段Name。程序的输出为:
姓名张冲
部门系统开发部
工资28000
结构体指针
可以定义指向结构体的指针。
package main
import "fmt"
type Employee struct {
Name,Department string
Salary float32
}
func main() {
//方式一
var employee1 = &Employee{
Name: "张冲",
Department: "系统研发部",
Salary: 18000,
}
//方式二
var employee2 = new(Employee)
employee2.Name = "易文杰"
fmt.Println(employee1.Name)
fmt.Println((*employee1).Name)
fmt.Println(employee2.Name)
fmt.Println((*employee2).Name)
}
上面的程序中,employee1和employee2是一个指向Employee结构体的指针。(*employee1).Name是访问employee1中的Name字段。程序的输出为:
张冲
张冲
易文杰
易文杰
在Go中我们可以使用employee.Name替代显示解引用(*employee).Name来访问Name字段。

浙公网安备 33010602011771号