1. 结构体的定义和初始化
package main import "fmt" func main() { /* 结构体:是由一系列具有相同类型或不同类型的数据构成的数据集合 结构体成员是由一系列的成员变量构成,这些成员变量也被称为“字段” */ //1.方法一 var p1 Person fmt.Println(p1) // { 0 } p1.name = "王二狗" p1.age = 30 p1.sex = "男" p1.address = "北京市" fmt.Printf("姓名:%s,年龄:%d,性别:%s,地址:%s ",p1.name,p1.age,p1.sex,p1.address) //2.方法二 p2 := Person{} fmt.Println(p2) // { 0 } p2.name = "Ruby" p2.age = 28 p2.sex= "女" p2.address = "上海市" fmt.Printf("姓名:%s,年龄:%d,性别:%s,地址:%s ",p2.name,p2.age,p2.sex,p2.address) //3.方法三 p3 := Person{name :"如花",age :20,sex:"女",address:"杭州市"} fmt.Println(p3) p4 := Person{ name:"隔壁老王", age : 40, sex :"男", address:"武汉市", } fmt.Println(p4) //4.方法四 p5 := Person{"李小花",25,"女","成都"} fmt.Println(p5) } //1.定义结构体 //Person是类型,这个类型有一个大的分类叫结构体 type Person struct { name string age int sex string address string }
2. 结构体指针
package main import "fmt" func main() { /* 数据类型: 值类型:int,float,bool,string,array,struct 引用类型:slice,map,function,pointer 通过指针: new(),不是nil,空指针 指向了新分配的类型的内存空间,里面存储的零值。 */ //1.结构体是值类型 p1 := Person{"王二狗",30,"男","北京市"} fmt.Println(p1) fmt.Printf("%p,%T ",&p1,p1) p2 := p1 fmt.Println(p2) fmt.Printf("%p,%T ",&p2,p2) p2.name = "李小花" fmt.Println(p2) fmt.Println(p1) //2.定义结构体指针 var pp1 *Person pp1 = &p1 fmt.Println(pp1) fmt.Printf("%p,%T ",pp1,pp1) fmt.Println(*pp1) //(*pp1).name = "李四" pp1.name = "王五" fmt.Println(pp1) fmt.Println(p1) //使用内置函数new(),go语言中专门用于创建某种类型的指针的函数 pp2 := new(Person) fmt.Printf("%T ",pp2) fmt.Println(pp2) //(*pp2).name pp2.name = "Jerry" pp2.age = 20 pp2.sex = "男" pp2.address= "上海市" fmt.Println(pp2) pp3 := new(int) fmt.Println(pp3) fmt.Println(*pp3) } type Person struct { name string age int sex string address string }
package main import "fmt" // 构造函数 type person struct { name string age int } type dog struct { name string } // 构造函数:约定成俗用new开头 // 返回的是结构体还是结构体指针 // 当结构体比较大的时候尽量使用结构体指针,减少程序的内存开销 // 把一个地址拷贝多次也不会有多大的内存开销 func newPerson(name string, age int) *person { return &person{ name: name, age: age, } } func newDog(name string) dog { return dog{ name: name, } } func main() { p1 := newPerson("yang", 18) p2 := newPerson("mo", 9000) fmt.Println(p1, p2) d1 := newDog("yang") fmt.Println(d1) }
3. 匿名字段模拟继承
package main import "fmt" func main() { /* 匿名结构体和匿名字段: 匿名结构体:没有名字的结构体, 在创建匿名结构体时,同时创建对象 变量名 := struct{ 定义字段Field }{ 字段进行赋值 } 匿名字段:一个结构体的字段没有字段名 匿名函数: */ s1 := Student{name:"张三",age:18} fmt.Println(s1.name,s1.age) //张三 18 func (){ fmt.Println("hello world...") //hello world... }() s2 := struct{ name string age int }{ name:"李四", age:19, } fmt.Println(s2.name,s2.age) //李四 19 //w1 := Worker{name:"王二狗",age:30} //fmt.Println(w1.name,w1.age) w2 := Worker{"李小花",32} fmt.Println(w2) //{李小花 32} fmt.Println(w2.string) //李小花 fmt.Println(w2.int) //32 } type Worker struct { //name string //age int string //匿名字段 int //匿名字段,默认使用数据类型作为名字,那么匿名字段的类型就不能重复,否则会冲突 //string } type Student struct { name string age int }
结构体的匿名字段:
可以用字段来创建结构,这些字段只包含一个没有字段名的类型。这些字段被称为匿名字段。
在类型中,使用不写字段名的方式,使用另一个类型
type Human struct { name string age int weight int } type Student struct { Human // 匿名字段,那么默认Student就包含了Human的所有字段 speciality string } func main() { // 我们初始化一个学生 mark := Student{Human{"Mark", 25, 120}, "Computer Science"} // 我们访问相应的字段 fmt.Println("His name is ", mark.name) fmt.Println("His age is ", mark.age) fmt.Println("His weight is ", mark.weight) fmt.Println("His speciality is ", mark.speciality) // 修改对应的备注信息 mark.speciality = "AI" fmt.Println("Mark changed his speciality") fmt.Println("His speciality is ", mark.speciality) // 修改他的年龄信息 fmt.Println("Mark become old") mark.age = 46 fmt.Println("His age is", mark.age) // 修改他的体重信息 fmt.Println("Mark is not an athlet anymore") mark.weight += 60 fmt.Println("His weight is", mark.weight) }
可以使用"."的方式进行调用匿名字段中的属性值
实际就是字段的继承
其中可以将匿名字段理解为字段名和字段类型都是同一个
基于上面的理解,所以可以
mark.Human = Human{"Marcus", 55, 220}
和mark.Human.age -= 1
若存在匿名字段中的字段与非匿名字段名字相同,则最外层的优先访问,就近原则
通过匿名访问和修改字段相当的有用,但是不仅仅是struct字段哦,所有的内置类型和自定义类型都是可以作为匿名字段的。
4. 结构体嵌套
package main import "fmt" func main() { /* 结构体嵌套:一个结构体中的字段,是另一个结构体类型。 has a */ b1 := Book{} b1.bookName = "西游记" b1.price = 45.8 s1 := Student{} s1.name = "王二狗" s1.age = 18 s1.book = b1 //值传递 fmt.Println(b1) fmt.Println(s1) fmt.Printf("学生姓名:%s,学生年龄:%d,看的书是:《%s》,书的价格是:%.2f ",s1.name,s1.age,s1.book.bookName,s1.book.price) s1.book.bookName = "红楼梦" fmt.Println(s1) fmt.Println(b1) b4 := Book{bookName:"呼啸山庄",price:76.9} s4 := Student2{name:"Ruby",age:18,book:&b4} fmt.Println(b4) fmt.Println(s4) fmt.Println(" ",s4.book) s4.book.bookName = "雾都孤儿" fmt.Println(b4) fmt.Println(s4) fmt.Println(" ",s4.book) s2 := Student{name:"李小花",age:19,book:Book{bookName:"Go语言是怎样炼成的",price:89.7}} fmt.Println(s2.name,s2.age) fmt.Println(" ",s2.book.bookName,s2.book.price) s3 := Student{ name:"Jerry", age:17, book:Book{ bookName:"十万个为啥", price:55.9, }, } fmt.Println(s3.name,s3.age) fmt.Println(" ",s3.book.bookName,s3.book.price) } //1.定义一个书的结构体 type Book struct { bookName string price float64 } //2.定义学生的结构体 type Student struct { name string age int book Book } type Student2 struct { name string age int book *Book // book的地址 }
5. 结构体OOP
package main import "fmt" func main() { /* 面向对象:OOP Go语言的结构体嵌套: 1.模拟继承性:is - a type A struct{ field } type B struct{ A //匿名字段 } 2.模拟聚合关系:has - a type C struct{ field } type D struct{ c C //聚合关系 } */ //1.创建父类的对象 p1 := Person{name:"张三",age:30} fmt.Println(p1) fmt.Println(p1.name,p1.age) //2.创建子类的对象 s1 := Student{Person{"李四",17},"千锋教育"} fmt.Println(s1) s2 :=Student{Person:Person{name:"rose",age:19},school:"北京大学"} fmt.Println(s2) var s3 Student s3.Person.name = "王五" s3.Person.age = 19 s3.school = "清华大学" fmt.Println(s3) //提升字段 s3.name = "Ruby" s3.age = 16 fmt.Println(s3) fmt.Println(s1.name,s1.age,s1.school) fmt.Println(s2.name,s2.age,s2.school) fmt.Println(s3.name,s3.age,s3.school) /* s3.Person.name---->s3.name Student结构体将Person结构体作为一个匿名字段了 那么Person中的字段,对于Student来讲,就是提升字段 Student对象直接访问Person中的字段 */ } //1.定义父类 type Person struct { name string age int } //2.定义子类 type Student struct { Person //模拟继承结构 school string //子类的新增属性 }