go之结构体
什么是结构体
结构体是用户定义的类型,表示若干个字段的集合,有时应该把数据整合一起,而不是让这些数据没有联系,这种情况下可以使用结构体
语法
// 结构体
//type关键字 结构体名字 struct{
// 字段1 字段类型
// 字段2 字段类型
//}
结构体定义
type Person struct { // 如果小写,在其他包使用不到Person结构体
Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
age uint8
Sex string
}
使用结构体
结构体是值类型,有默认零值,如果当函数参数传递,在函数中修改,不会影响原来的
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 }
}
定义并初始化
按位置初始化
按照顺序,有几个字段,必须传几个字段
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 男}
}
按关键字初始化
不用按顺序,字段不用都传
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 男}
}
字段的取值赋值
通过.
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
}
结构体零值
不初始化有默认零值,零值是各个字段的零值
package main
import "fmt"
type Person struct { // 如果小写,在其他包使用不到Person结构体
Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
age uint8
Sex string
}
func main() {
var p Person
fmt.Println(p) //{ 0 }
}
匿名结构体
结构体没有名字和type关键字,一般定义在函数内部,只使用一次
好处是:多个变量可以包装到一个变量中
func main() {
a:= struct {
age int
name string
}{19,"彭于晏"}
fmt.Println(a.name)
fmt.Println(a.age)
fmt.Println(a)
}
结构体指针
还可以创建只想结构体的指针
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 字段。该程序会输出
First Name: Sam Age: 55
Go 语言允许我们在访问 firstName 字段时,可以使用 emp8.firstName 来代替显式的解引用 (*emp8).firstName。
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 字段,该程序会输出:
First Name: Sam Age: 55
结构体当函数参数传递
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 男}
}
结构体指针当函数参数传递
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 男}
}
匿名字段
字段没有名字,跟结构体是否匿名没有必然联系
作用:可以做字段提升,实现面向对象的继承
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}
}
结构体嵌套
结构体中套结构体
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自己的
}
导出结构体和字段
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包
package entity
type Person struct { // 大写开头,外包才可以用
Name string
age int
}
结构体是值类型
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{
//
//}
}

浙公网安备 33010602011771号