结构体的定义
结构体是一种用户自定义的数据类型,它由一组字段组成,每个字段可以是任意基本类型或其他结构体类型。结构体在Go语言中被广泛使用,它可以用来表示复杂的数据结构,比如二叉树、链表、图等。
结构体的形式如下:
type name struct{
value1 type1
value2 type2
......
}
下面是一个实际一点的例子
type Person struct {
name string
age int
sex string
}
上面的代码定义了一个名为Person的结构体,它有三个字段,分别是name、age和sex,它们的类型分别为string、int和string。通过这个结构体就可以表示一个人的基本信息。
结构体的创建
type Person struct {
name string
age int
sex string
}
- 使用new
ms:=new(myStruct)
- 使用结构体字面量
var ms myStruct
- 间接使用new创建
ms:=&msStruct{"张三",18,"男"}
初始化结构体
ms:={“张三”,18,“男”}
这种方法初始化必须按照字段在结构体定义是的顺序填写
ms:={name:“张三”,sex:“男”}
这种方法指定某些字段的值,不必按照顺序,而且一些字段可以被忽略,这里的age字段被忽略且值为0
结构体值的使用
结构体是Go语言中的核心组件,用于组织和表示复杂的数据结构。一旦我们有了结构体的实例(也称为结构体值),如何使用它们呢?这部分将详细讨论如何访问、修改和利用结构体的值。
访问结构体的字段
每个结构体的字段都可以通过.运算符来访问。
type Book struct {
Title string
Author string
Price int
}
// 创建一个Book类型的实例
myBook := Book{"", "Alan A. A. Donovan", 38}
// 访问结构体字段
title := myBook.Title
我们定义了一个Book结构体并初始化了一个myBook实例。使用.运算符访问myBook的Title字段。
修改结构体的字段
可以直接通过=赋值运算符修改结构体的字段。
// 修改结构体字段
myBook.Pages = 400
我们使用前面创建的myBook实例,直接为myBook的Pages字段赋新值,myBook的Pages字段值现在为400。
结构体的使用
import(
"fmt",
"string"
)
type Person struct{
firstName string
lastName string
}
func upPerson(p *Person){
p.firstName=strings.ToUpper(p.firstName)
p.lastName=strings.ToUpper(p.lastName)
}
func main(){
var per1 Person
per1.firstName="zhang"
per1.lastName="sang"
upPerson(&per1)
fmt.Printf("这个人的名字是%s %s\n",per1.firstName,per1.lastName)
per2:=new(Person)
per2.firstName="zhang"
per2.lastName="sang"
upPerson(&per2)
fmt.Printf("这个人的名字是%s %s\n",per2.firstName,per2.lastName)
per3:=&Person{"zhang","sang"}
upPerson(per3)
fmt.Printf("这个人的名字是%s %s\n",per3.firstName,per3.lastName)
}
注意
由于go的类型转换规则非常严格,当给一个结构体a取别名b,类型为a和类型为b的变量相互赋值时就要进行类型转换
type number struct{
f int
}
type nb number
a:=number{1}
b:=nb{2}
a=b
//取了别名就不能直接赋值了a=b
//需要类型转换
//a=number(b)
fmt.Println(a)
结构体作为函数参数
结构体也可以被用作函数的参数,允许我们在函数内部操作结构体的值。
示例:
func PrintBookInfo(b Book) {
fmt.Printf(“Title: %s, Author: %s, Pages: %d\n”, b.Title, b.Author, b.Pages)
}
// 使用函数
PrintBookInfo(myBook)
输入:我们定义了一个PrintBookInfo函数,其参数为Book类型,并使用了myBook实例作为参数。
处理过程:在函数内部,我们访问结构体的各个字段,并打印其值。
输出:控制台输出书籍的详细信息。
结构体中的匿名字段
匿名字段就是没有名字只有类型的字段,在一个结构体中一种类型只能有一个匿名字段。
通过这个可以模拟类似继承的行为
type first struct{
f1 int
f2 int
}
type second struct{
s1 int
s2 int
first
}
func main(){
sec:=new(second)
sec.s1=1
sec.s2=2
sec.f1=3
sec.f2=4
fmt.Println(sec)
}
结构体嵌套产生的命名冲突
当一个结构体中两个字段有相同的名字的时候就会发生命名冲突(通过匿名字段实现继承的时候)
比如下面这几个例子
- 相同名字在同层次结构体中出现
type A struct{
a int
}
type B struct{
a int
b int
}
type C struct{
A
B
}
var c C
c.a
使用c.a就会报错,因为编译器分不清是c.A.a还是c.B.a
- 相同名字字段在不同结构体层次出现
type D struct{
B
b float32
}
var d D
d.b
这里使用d.b就没有问题,d.b和d.B.b是可以区分的。