3.11 Go Struct structure
Golang support OOP object-oriented programming.
Go of the structure struct
as a python class
.
Go on struct achieve OOP features, only the combination of composition
this feature.
2. The structure concept
1) The properties of a class of transaction extract a new data type is a structure.
2) to create multiple instances of structures.
3) may be Student structure, it may be Animal, Person structure.
3. The structure features
1) struct is used to define complex data structures
2) struct may comprise a plurality of fields
3) struct method can be defined (note not function, is the golang method)
4) struct value type may be
5) struct type can be nested
6) Go no class, only struct type
7) the structure is defined types can not be transferred to other types of strong
8) may be added to each field struct tag, this tag may be acquired reflection mechanism, such as a scene json serialization and deserialization.
4. The structure is defined
package main import "fmt" type Person struct { Name string Age int } func main() { //声明方式 p1 := Person{"小黑", 18} //有序赋值,并且必须包含所有字段,否则报错 p2 := Person{Age: 18} //关键词赋值,未赋值字段有空值 fmt.Println(p1) fmt.Println(p2) }
Exercise struct
package main import "fmt" //声明结构体名称Stu type Stu struct { Name string //结构体字段 Age int //如未赋值有默认空值 Address string Score int } //结构体可以定义复杂的类型 type Person struct { Name string Age int Score [5]float64 //容量为5的数组 prt *int //指针类型 slice []int //int类型切片 map1 map[string]string //map类型字段 //slice和map默认值是nil,必须make初始化才可使用 } //结构体是值类型,不同结构体实例之间互不影响 type Monster struct { Name string Age int } func main() { //声明结构体类型变量 var stu1 Stu //结构体可以通过 . 的方式赋值,声明赋值方式一 stu1.Name = "小黑" stu1.Age = 18 stu1.Address = "沙河" stu1.Score = 100 fmt.Printf("stu1的名字=%v 年纪=%v 住址=%v 分数=%v\n", stu1.Name, stu1.Age, stu1.Address, stu1.Score) //声明赋值方式二 monster1 := Monster{"红孩儿", 18} monster2 := Monster{"女妖怪", 999} //两个结构体实例,内存地址不一样,确保独立 fmt.Printf("monster1地址:%p\n", &monster1) fmt.Printf("monster2地址:%p\n", &monster2) //声明方式三 //用来分配内存,主要用来分配值类型,比如int、struct。返回指向类型的 指针 //此时m1是一个指针 var m1 *Monster = new(Monster) //给m1赋值 (*m1).Name = "孙悟空" //编译器自动识别 同于 m1.Name="孙悟空" (*m1).Age = 9999 //同上 fmt.Println(*m1) //此时m1是指针变量,加上*取值 //声明方式四 m2 := &Monster{ "猪八戒", 888, } fmt.Println(*m2) //第三、第四种返回结构体指针,go编译器自动识别,简化程序员心智负担,建议用1、2方法 }
4.1.1. Anonymous structure
No name structure
package main import "fmt" func main() { //匿名函数 func() { fmt.Println("我是匿名函数") }() //匿名结构体 p1 := struct { name string age int }{ name: "张三", age: 18, } fmt.Println(p1) }
4.1.2. AnonymousField
package main import "fmt" func main() { type student struct { string //匿名字段,类型当做字段名 int } s1 := student{ "吴亦凡", 18, } fmt.Println(s1.string, s1.int) }
4.1.3. Nesting structure
Object-oriented: aggregation relationship
A class as a property of another class
package main import "fmt" type Book struct { bookName string price float64 author string } type Person struct { name string age int book Book //继承Book结构体的字段 ,模拟聚合关系 } func main() { //先定义好的book对象 b1 := Book{"如何找到女朋友", 999.999, "alex金角大王"} p1 := Person{"武沛奇", 26, b1} //b1就是Book结构体类型,武沛奇买了一本书 fmt.Printf("姓名:%s,年纪:%d,书名:%s,价格:%.2f,书的作者:%s\n", p1.name, p1.age, p1.book.bookName, p1.book.price, p1.book.author) //声明初始化book对象,一行搞定 p2 := Person{"萧峰", 25, Book{"如何找到男朋友", 3.58, "超哥著作"}} fmt.Printf("姓名:%s,年纪:%d,书名:%s,价格:%.2f,书的作者:%s\n", p2.name, p2.age, p2.book.bookName, p2.book.price, p2.book.author) }
结构体嵌套练习
Students and shelving,
package main import "fmt" type Book struct { bookName string price float64 } type Student struct { name string age int books []*Book } func main() { b1 := Book{"霸道总裁爱上我", 120.22} b2 := Book{"斗破苍穹", 12.5} b3 := Book{"我和师姐的故事", 15.5} //定义书架,默认没有书,可以容纳10本书 //用Book就是值拷贝,*Book就是放入书的内存地址 bookSlice := make([]*Book, 0, 10) //注意需要传入地址 bookSlice = append(bookSlice, &b1, &b2, &b3) //创建一个学生 s1 := Student{"小猪沛奇", 3, bookSlice} fmt.Printf("姓名:%s,年纪:%d\n", s1.name, s1.age) //查看书架上书的信息 for i := 0; i < len(s1.books); i++ { book := s1.books[i] fmt.Printf("\t第%d本书,书名:%s,书价格:%.2f\n", i+1, (*book).bookName, book.price) } //创建图书方式二 //初始化创建时候,必须对切片分配内存 s2 := Student{"特斯拉车主alex", 46, make([]*Book, 0, 10)} //放入书架的书,放入书的内存地址 s2.books = append(s2.books, &Book{"斗罗大陆", 55.3}, &Book{"python入门到放弃", 1.28}, &Book{"王思聪与三个网红的一天", 999999.99}) fmt.Printf("学生名:%s,学习年龄:%d\n", s2.name, s2.age) //输入所有s2学生看的书 for k, v := range s2.books { fmt.Printf("\t第%d本书,书名:%s,价格:%.2f\n", k+1, v.bookName, v.price) } }
4.1.4 Object-Oriented: inheritance
A class as a subclass of another class: subclass parent
Inheritance: A second object-oriented features, describe the relationship between two classes for
Subclass, derived class, subClass inherit the parent class (super class, the base class, superClass)
Subclasses can access existing properties and methods of the parent class directly
Subclass can add your own properties and methods
Subclass existing methods can also override the parent class
通过匿名字段的方式,进行嵌套,实现继承关系
package main import "fmt" //1.定义父类 type Person struct { name string age int } //2定义子类,匿名字段,Person即是 type Son struct { Person //模拟继承结构,继承父类的name,age属性 school string //子类的新增属性 } func main() { //父类 p1 := Person{"李靖", 999} fmt.Println(p1.name, p1.age) //子类赋值方式一,子类直接访问父类属性 var s2 Son s2.name = "娜扎" s2.age = 666 s2.school = "神仙学校" fmt.Println(s2, s2.name, s2.age, s2.school) //创建方式二,简写方式 s3 := Son{Person{"木吒", 667}, "神仙学校"} fmt.Println(s3, s3.name, s3.age, s3.school) //创建方式三,基于key-value写 s4 := Son{Person: Person{name: "金吒", age: 668}, school: "神仙学校"} fmt.Println(s4, s4.name, s4.age, s4.school) }
4.1.5 details of structure
- Field structure is continuous in memory
package main import "fmt" type Test struct { A int32 B int32 C int32 D int32 } func main() { var t Test fmt.Printf("a addr:%p\n", &t.A) fmt.Printf("b addr:%p\n", &t.B) fmt.Printf("c addr:%p\n", &t.C) fmt.Printf("d addr:%p\n", &t.D) }
- Structure is defined by the user, can be cast, but it must be exactly the same field, the number, type
- Redefine the structure of (re-type), the same effect on the structure
别名
- Each struct field, a Tag can be written, the tab may be obtained by reflection by the serialization, deserialization
package main import ( "encoding/json" "fmt" ) type User struct { UserName string `json:"姓名"` //反引号括起来的就是struct tag Sex string `json:"性别"` Score float32 `json:"成绩"` Age int32 `json:"年纪"` } func main() { user := &User{ UserName: "user01", Sex: "男", Score: 99.2, Age: 18, } //将user变量序列化为json格式字符串 data, _ := json.Marshal(user) fmt.Printf("json str:%s\n", string(data)) }
4.2 Memory Allocation structure
Look at the code
package main import "fmt" type Person struct { Name string Age int } func main() { //p1有自己的结构体内存地址, var p1 Person p1.Age = 10 p1.Name = "王大锤" //定义P2 指针类型,指向p1的内存地址 var p2 *Person = &p1 //两种形式一样,go编译器自动识别 fmt.Println((*p2).Age) fmt.Println(p2.Age) //修改p2的结构体值,也就是修改了p1的结构体值 p2.Name = "葫芦娃" fmt.Printf("输出结果 p2.Name=%v p1.Name=%v\n", p2.Name, p1.Name) fmt.Printf("输出结果(*p2).Name=%v p1.Name=%v\n", (*p2).Name, p1.Name) //查看p1和p2的内存地址 fmt.Printf("p1内存地址%p\n", &p1) //p2是指针变量,自己也有一块内存地址,p2的值指向 fmt.Printf("p2内存地址%p p2的值是%v\n", &p2, p2) }