struct
Go不是一个纯面向对象的编程语言。Go语言采用更灵活的"结构体"替代了"类"
Go并没有提供类(class),但是它提供了结构体(struct),方法(method)可以在结构体上添加。与类相类似,结构体提供了捆绑数据和方法的行为。
Go语言面向对象主要学习结构体(struct)、方法(method)、接口(interface)
1.1结构体的定义
type 类型名 struct{
成员属性1 类型1
成员属性2 类型2
成员属性3 类型3
}
Sample结构体实例化
package main
import "fmt"
type Teacher struct {
name string
age int
sex byte
}
func main() {
//1、var声明方式实例化结构体,初始化方式为:对象.属性=值
var t1 Teacher
fmt.Println(t1)
fmt.Printf("%T\n,%v\n,%q \n",t1,t1,t1)
t1.name="JackMa"
t1.age=10086
t1.sex=1
fmt.Println(t1)
fmt.Println("---------------")
//变量简短声明格式实例化结构体,初始化方式为:对象.属性=值
t2:=Teacher{}
t2.name="pink"
t2.age=132
t2.sex=1
fmt.Println(t2)
fmt.Println("-------------------------")
}
/*
{ 0 0}
main.Teacher
,{ 0 0}
,{"" '\x00' '\x00'}
{JackMa 10086 1}
---------------
{pink 132 1}
-------------------------
*/
1.2结构体语法糖
package main
import "fmt"
type teacher struct {
name string
age int8
sex byte
}
func SynSugar() {
//数组中的语法糖
arr:=[6]int{10,20,30,40,50,60}
arr2:=&arr
fmt.Println((*arr2)[len(arr)-1]) //返回60
fmt.Println(arr2[0]) //返回10
//切片的语法糖
arr3:=[4]int {100,200,300,400}
arr4:=&arr3
fmt.Println((*arr4)[len(arr3)-1]) //返回400
}
func main() {
//使用new()内置函数实例化struct
emp1:=new(teacher)
fmt.Printf("emp1:%T,\n%v\n,%p\n",emp1,emp1,emp1) //*main.teacher,&{ 0 0},0xc000004078
(*emp1).age=100
(*emp1).name="JackMa"
(*emp1).sex=1
fmt.Println("--------------")
fmt.Println(emp1) //&{JackMa 100 1}
fmt.Println(*emp1) //{JackMa 100 1}
fmt.Println("--------------")
SynSugar()
}
1.3结构体是值类型
深拷贝是拷贝值,浅拷贝是拷贝了指针。
package main
import "fmt"
type Dog struct {
name string
color string
age int
kind string
}
func main() {
//1、实现结构体的深拷贝
//struct 是值类型,默认的复制就是深拷贝
dog1:=Dog{"旺财","black",2,"我是旺财!"}
fmt.Printf("d1:%T,%v,%p\n",dog1,dog1,&dog1) //返回d1:main.Dog,{旺财 black 2 我是旺财!},0xc000042040
dog2:=dog1
fmt.Printf("dog2:%T,%v,%p\n",dog2,dog2,&dog2)
dog2.name="JackMa"
fmt.Println(dog2) //{JackMa black 2 我是旺财!}
fmt.Println("-------------------------")
//dog2.boyfriend="steven" 这里结构体里面没有定义的报错
//2、实现结构体浅拷贝,通过new()函数实现
dog4:=new(Dog)
dog4.name="Tony Ma"
dog4.color="white"
dog4.age=100
dog4.kind="cute"
fmt.Printf("dog4: %T,%v,%p\n",dog4,dog4,&dog4) //返回dog4: *main.Dog,&{Tony Ma white 100 cute},0xc000006030
}
1.4结构体作为参数返回值
结构体作为参数返回值有两种方式,值传递和参数传递。(这里我有个小困惑,go里面有引用参数传递吗?))
package main
import "fmt"
type Flower struct {
name,color string
}
func changeInfo(f Flower) {
f.name="月季"
f.color="pink"
}
func changeInfo2(f *Flower) {
f.name="喇叭花"
f.color="white"
}
//返回结构体
func getFlower1() Flower {
f:=Flower{"多肉","pink"}
return f
}
//返回结构体指针
func getFlower2() *Flower{
temp:=Flower{"芙蓉","ret"}
fmt.Printf("%T,%v,%p\n",temp,temp,&temp) //main.Flower,{芙蓉 ret},0xc000020500
f:=&temp
return f
}
func main() {
//结构体作为参数的用法
f1:=Flower{"玫瑰","red"}
fmt.Printf("%T,%v,%p\n",f1,f1,&f1)
changeInfo(f1)
fmt.Printf("%T,%v,%p\n",f1,f1,&f1) //main.Flower,{玫瑰 red},0xc0000203e0
fmt.Println("------------------")
changeInfo2(&f1) //加引用可变
fmt.Printf("%T,%v,%p\n",f1,f1,&f1) //main.Flower,{喇叭花 white},0xc0000203e0
//结构体作为对象返回值的用法
f2:=getFlower1()
f3:=getFlower2()
fmt.Println("-------------------")
fmt.Printf("%T,%v,%p\n",f2,f2,&f2) //main.Flower,{多肉 pink},0xc0000204e0
fmt.Printf("%T,%v,%p\n",f3,f3,&f3) //返回*main.Flower,&{芙蓉 ret},0xc000006030
}
getFlower2()函数里面的temp的地址和ret的结构体指针地址不一样。所以还是有引用传递的
1.5匿名结构体
匿名结构体就是不需要type来定义的结构体,创建匿名结构体时,同时要创建对象。匿名结构体由结构体定义和键值对初始化两部分组成。
package main
import (
"fmt"
"math"
)
func main() {
//匿名函数
res:= func(a,b float64) float64{
return math.Pow(a,b)
}(2,3)
fmt.Println(res) //返回8
//匿名结构体
addr:= struct {
province,city string
}{"西藏","拉萨"}
fmt.Println(addr) //返回{西藏 拉萨}
cat:= struct {
name,color string
age int8
}{"黑猫","白色",10}
fmt.Println(cat) //{黑猫 白色 10}
}
1.6结构体的匿名字段
package main
import "fmt"
type User struct {
string
byte
int8
float64
}
func main() {
//实例化结构体
user1:=User{"steven",'m',35,177.5}
fmt.Println(user1) //返回{steven 109 35 177.5}
//如果想一次输出姓名、年龄、身高、性别
fmt.Printf("姓名:%s\n",user1.string) //返回姓名:steven
fmt.Printf("身高:%.2f\n",user1.float64) //身高:177.50
fmt.Printf("性别:%c\n",user1.byte) //性别:m
fmt.Printf("年龄:%d\n",user1.int8) //年龄:35
}
1.7 结构体嵌套
结构体嵌套就是将一个结构体作为另一个结构体的属性(字段),这种结构就是结构体嵌套。结构体嵌套可以模拟为面向对象编程的以下两种关系
- 聚合关系:一个类作为另一个类的属性。
- 继承关系:一个类作为另一个类的子类。子类和符类的关系。
sample聚合关系
package main
import "fmt"
type Address struct {
province,city string
}
type person struct {
name string
age int
address *Address
}
func main() {
//模拟结构体对象之间的聚合关系
p:=person{}
p.name="Steven"
p.age=19
//赋值方法
addr:=Address{}
addr.province="西藏"
addr.city="拉萨"
p.address=&addr
fmt.Println("姓名:",p.name,"age:",p.age,"province:",p.address.province,"city:",p.address.city)
fmt.Println("----------------------------")
p.address.city="林芝"
fmt.Println("姓名:",p.name,"age:",p.age,"province:",p.address.province,"city:",p.address.city)
//修改赋值对象addr是否影响Person对象的数据
addr.city="日喀则"
fmt.Println("姓名:",p.name,"age:",p.age,"province:",p.address.province,"city:",p.address.city)
fmt.Printf("------------------\n")
//赋值方法2
p.address=&Address{"青海","西宁"}
fmt.Println("姓名:",p.name,"age:",p.age,"province:",p.address.province,"city:",p.address.city)
}
/*
返回结果:
姓名: Steven age: 19 province: 西藏 city: 拉萨
----------------------------
姓名: Steven age: 19 province: 西藏 city: 林芝
姓名: Steven age: 19 province: 西藏 city: 日喀则
------------------
姓名: Steven age: 19 province: 青海 city: 西宁
*/
1.8模仿继承关系
studentS继承PersonS
package main
import "fmt"
type PersonS struct {
name string
age int
sex string
}
type studentS struct {
PersonS
studentNum int64
}
func main() {
//结构嵌套体模拟继承关系
p1:=PersonS{"JackMa",35,"男"}
fmt.Println(p1)
fmt.Println("--------------------------")
//实例化并初始化Student
//写法1
s1:=studentS{p1,1008611}
fmt.Println(s1)
//写法2
s2:=studentS{PersonS{"TonyMa",30,"男"},123456}
fmt.Println(s2)
//写法3
s3:=studentS{}
s3.studentNum=10323
s3.age=102311
s3.sex="男"
}