1.关于 Golang 结构体
- Golang 中没有“类”的概念,Golang 中的结构体和其他语言中的类有点相似。和其他面向对象语言中的类相比,Golang 中的结构体具有更高的扩展性和灵活性。
- Golang 中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型就无法满足需求了,
- Golang 提供了一种自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体,英文名称 struct。
- 也就是我们可以通过 struct 来定义自己的类型了。
2.结构体定义初始化的几种方法
2.1结构体的定义
使用 type 和 struct 关键字来定义结构体,具体代码格式如下
type 类型名 struct {
字段名 字段类型
字段名 字段类型
…
}
/* 注意:结构体首字母可以大写也可以小写,大写表示这个结构体是公有的, 在其他的包里面 可以使用。小写表示这个结构体是私有的,只有这个包里面才能使用。 */ type person struct { sex string // 可以写在一行 name,city string age int }
2.2六种实例化方法
package main import "fmt" /* 注意:结构体首字母可以大写也可以小写,大写表示这个结构体是公有的, 在其他的包里面 可以使用。小写表示这个结构体是私有的,只有这个包里面才能使用。 */ type person struct { sex string // 可以写在一行 name, city string age int } func main() { // 1.结构体实例化(第一种方法) var p1 person p1.age = 22 p1.name = "GJH" p1.city = "北京" p1.sex = "男" fmt.Println(p1) //{男 GJH 北京 22} fmt.Println(p1.sex) // 男 //2.第二种实例化 var p2 = new(person) p2.sex = "男" p2.name = "GJH" fmt.Println(p2) // &{男 GJH 0} p2 是一个结构体指针 //3.使用&对结构体进行取地址操作相当于对该结构体类型进行了一次 new 实例化操作。 p3 := &person{} p3.sex = "女" p3.name = "LYL" fmt.Println(p3) //&{女 LYL 0} //4.结构体实例化(第四种方法) 键值对初始化 p4 := person{ sex: "男", age: 22, //注意:最后一个属性的","要加上 } fmt.Println(p4) //{男 22} //5.结构体实例化(第五种方法) 结构体指针进行键值对初始化 p5 := &person{ name: "码云", } fmt.Println(p5) //&{ 码云 0} //6.结构体实例化(第六种方法) 使用值的列表初始化 /* 初始化结构体的时候可以简写,也就是初始化的时候不写键,直接写值: 使用这种格式初始化时,需要注意: 1.必须初始化结构体的所有字段。 2.初始值的填充顺序必须与字段在结构体中的声明顺序一致。 3.该方式不能和键值初始化方式混用 4.字段数量一致 */ p7 := &person{ "男", "马化腾", "北京", 22, } fmt.Println(p7) //&{男 马化腾 北京 22} }
3.结构体属性类型使用
package main import "fmt" /* 结构体的字段类型可以是:基本数据类型、也可以是切片、Map 以及结构体 如果结构体的字段类型是: 指针,slice,和map的零值都是 nil ,即还没有分配空间 如果需要使用这样的字段,需要先make,才能使用. */ type Person struct { Name string Age int Hobby []string map1 map[string]string } func main() { var p Person p.Name = "张三" p.Age = 20 p.Hobby = make([]string, 2, 6) p.Hobby[0] = "写代码" p.Hobby[1] = "打篮球" p.map1 = make(map[string]string) p.map1["address"] = "北京" p.map1["phone"] = "1324325325" fmt.Printf("%#v ", p) //main.Person{Name:"张三", Age:20, Hobby:[]string{"写代码", "打篮球", "睡觉"}, map1:map[string]string{"address":"北京", "phone":"1324325325"}} fmt.Printf("%v", p.Hobby) //[写代码 打篮球 睡觉] }
4.结构体嵌套
package main import "fmt" type User1 struct { Name string Age int ccc string User2 User2 // 这就是结构体的嵌套 获取的时候要加上结构体名字 User2.属性 User3 // 这就是结构体的匿名嵌套 匿名嵌套 获取的属性的时候 会自己在结构体内寻找 } type User2 struct { aaa string bbb int ccc string } type User3 struct { Hobby string school string AddTime string ccc string } func main() { var u User1 u.Name = "GJH" u.Age = 22 u.ccc = "ccc" /* 错误写法 u.aaa = "asdasd" // 如果结构体不是写的匿名嵌套 要加上结构体名字进行获取属性 */ // 正确写法 u.User2.aaa = "aaa" u.User2.bbb = 11111 u.User2.ccc = "ccc2" // 直接修改User3的AddTime u.school = "清华" u.AddTime = "2021-03-27" u.User3.ccc = "ccc3" fmt.Println(u) // {GJH 22 ccc {aaa 11111 ccc2} { 清华 2021-03-27 ccc3}} /* 注意: 1.当访问结构体成员时会先在结构体中查找该字段,找不到再去匿名结构体中查找。 2.当有相同属性的时候 访问要加上结构体的名字 :u.User2.ccc = "ccc2" */ }
5.结构体方法
/* 结构体可以描述现实生活中的任何事物,生活中的任何事物都可以当做结构体对象 我们可以把客观事物封装成结构体 : 汽车 汽车有属性:颜色 大小 重量 发动机 轮胎 ... 汽车行为 也叫方法: run 跑 小狗 属性:颜色 大小 品种 性别 .. 行为:叫 、闻一闻 舔一舔 咬一咬 电风扇 属性: 颜色 大小 高低... 行为:转动 人也是一个结构体对象: 属性: 名字 年龄 性别 ... 行为:工作 运动 .. */ package main import "fmt" type Person struct { Name string Age int Sex string height int } func (p Person) PrintInfo() { fmt.Printf("姓名:%v 年龄:%v ", p.Name, p.Age) } func main() { var p1 = Person{ Name: "张三", Age: 20, Sex: "男", } p1.PrintInfo() //姓名:张三 年龄:20 var p2 = Person{ Name: "李四", Age: 30, Sex: "男", } p2.PrintInfo() //姓名:李四 年龄:30 p1.PrintInfo() //姓名:张三 年龄:20 }
6.结构体继承
package main import "fmt" //父亲结构体 type Animal struct { Name string } func (a Animal) run() { fmt.Printf("%v 在运动 ", a.Name) } //子结构体 type Dog struct { Age int Animal //结构体嵌套 继承 } func (d Dog) wang() { fmt.Printf("%v 在旺旺 ", d.Name) } func main() { var d = Dog{ Age: 20, Animal: Animal{ Name: "阿奇", }, } d.run() //阿奇 在运动 d.wang() //阿奇 在旺旺 }