go之结构体
什么是结构体
结构体是用户定义的类型,表示若干个字段的集合,有时应该把数据整合一起,而不是让这些数据没有联系,这种情况下可以使用结构体
语法
1 2 3 4 5 | // 结构体 //type关键字 结构体名字 struct{ // 字段1 字段类型 // 字段2 字段类型 //} |
结构体定义
1 2 3 4 5 | type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } |
使用结构体
结构体是值类型,有默认零值,如果当函数参数传递,在函数中修改,不会影响原来的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p Person // 没有初始化,有零值,零值是每个字段的零值 fmt.Println(p.age) //0 有默认零值,字段的零值 fmt.Println(p) //{ 0 } } |
定义并初始化
按位置初始化
按照顺序,有几个字段,必须传几个字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p Person=Person{ "zys" ,18, "男" } fmt.Println(p) //{zys 18 男} } |
按关键字初始化
不用按顺序,字段不用都传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p Person=Person{Sex: "男" ,age:19} fmt.Println(p) //{ 19 男} } |
字段的取值赋值
通过.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p Person=Person{Sex: "男" ,age:19} fmt.Println(p) //{ 19 男} fmt.Println(p.Name) p.Name= "xx" fmt.Println(p.Name) //xx } |
结构体零值
不初始化有默认零值,零值是各个字段的零值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p Person fmt.Println(p) //{ 0 } } |
匿名结构体
结构体没有名字和type关键字,一般定义在函数内部,只使用一次
好处是:多个变量可以包装到一个变量中
1 2 3 4 5 6 7 8 9 | func main() { a:= struct { age int name string }{19, "彭于晏" } fmt.Println(a.name) fmt.Println(a.age) fmt.Println(a) } |
结构体指针
还可以创建只想结构体的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package main import ( "fmt" ) type Employee struct { firstName, lastName string age, salary int } func main() { emp8 := &Employee{ "Sam" , "Anderson" , 55, 6000} fmt.Println( "First Name:" , (*emp8).firstName) fmt.Println( "Age:" , (*emp8).age) } |
在上面程序中,emp8 是一个指向结构体 Employee
的指针。(*emp8).firstName
表示访问结构体 emp8
的 firstName
字段。该程序会输出
1 2 | First Name: Sam Age: 55 |
Go 语言允许我们在访问 firstName
字段时,可以使用 emp8.firstName
来代替显式的解引用 (*emp8).firstName
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package main import ( "fmt" ) type Employee struct { firstName, lastName string age, salary int } func main() { emp8 := &Employee{ "Sam" , "Anderson" , 55, 6000} fmt.Println( "First Name:" , emp8.firstName) fmt.Println( "Age:" , emp8.age) } |
在上面的程序中,我们使用 emp8.firstName
来访问 firstName
字段,该程序会输出:
1 2 | First Name: Sam Age: 55 |
结构体当函数参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p =Person{ "zys" ,18, "男" } test5(p) fmt.Println( "----" ,p) // p 不受影响 ---- {zys 18 男} } func test5(p Person) { fmt.Println(p) //{zys 18 男} p.Name= "lyf" fmt.Println(p) //{lyf 18 男} } |
结构体指针当函数参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package main import "fmt" type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { var p = &Person{ "zys" , 18, "男" } test6(p) //指针传入,地址copy传入,改了就影响原来 fmt.Println( "----" , p) // p 受影响 ---- &{lyf 18 男} } func test6(p *Person) { fmt.Println(p) //&{zys 18 男} p.Name = "lyf" //(*p).Name="lyf" fmt.Println(p) //&{lyf 18 男} } |
匿名字段
字段没有名字,跟结构体是否匿名没有必然联系
作用:可以做字段提升,实现面向对象的继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package main import "fmt" type Animal struct { string // 字段没有名字,但是不能出现两个同种类型的字段 ,字段名就是类型名 int } func main() { //var a =Animal{"小鸭子",1} var a = Animal{string: "小鸭子" , int: 1} fmt.Println(a) //{小鸭子 1} } |
结构体嵌套
结构体中套结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package main import "fmt" func main() { type Animal struct { Name string age int } type Dog struct { //Name string //age int // 简写成--->结构体嵌套 //animal Animal Animal //匿名字段,Animal字段匿名了,字段名就是类型名,而且不用写name和age了 //Dog比Animal多的字段 Speak bool } //var dog =Dog{Animal{"二哈",3},true} var dog = Dog{Animal: Animal{ "二哈" , 3}, Speak: true} //面向对象继承,1 少写代码 2 子类对象.属性 如果子类没有,直接使用父类的 fmt.Println(dog.Name) //二哈 dog的name本来是Animal的,使用了匿名字段,字段提升了 //如果Animal不是匿名字段,不能提升 fmt.Println(dog.Animal.Name) //二哈 指名道姓用 dog.Animal 相当于 super() //Dog中有Name,Animal 用了匿名字段,Name冲突了,会优先使用Dog自己的 } |
导出结构体和字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package main import ( "day01/entity" "fmt" ) type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { //var p =entity.Person{"lyf",37} // age 小写,外包包不能用 var p =entity.Person{Name: "lyf" } fmt.Println(p) //{lyf 0} } |
entity包
1 2 3 4 5 6 7 8 | package entity type Person struct { // 大写开头,外包才可以用 Name string age int } |
结构体是值类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package main import ( "fmt" ) type Person struct { // 如果小写,在其他包使用不到Person结构体 Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到 age uint8 Sex string } func main() { //如果它的每一个字段都是可比较的,则该结构体也是可比较的。 //如果两个结构体变量的对应字段相等,则这两个变量也是相等的 var p1=Person{ "zys" ,19, "男" } var p2=Person{Name: "zys" ,age: 19,Sex: "男" } p2.age=20 if p1==p2{ fmt.Println( "p1 和p2 相等" ) } else { fmt.Println(1) //1 } //如果结构体包含不可比较的字段(有引用类型),则结构体变量也不可比较 //type Cat struct { //Name string //age int //wife []string // 可以有很多异性猫 //} //var c1 =Cat{"小野豹",3,[]string{"女朋友1号","女朋友2号"}} //var c2 =Cat{"小野豹",3,[]string{"女朋友1号","女朋友2号"}} //if c1==c2{ // //} } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构