整体来说,与C语言的定义方式相同
type struct_name struct{...}
结构体的字段可以是任何类型,甚至是结构体本身,也可以是函数或者接口
与C++中的类,很相似,但是go没有类的概念
type ueueQ struct{
a int
b float32}
一、
var temp ueueQ
temp = ueueQ{100,99.9}
二、
temp := ueueQ{100,99.9}
temp := ueueQ{a:100, b:99.9}
temp := ueueQ{b:99.9}
三、
var temp *ueueQ
temp =new(ueueQ)
temp.a =100
temp.b =99.9(*temp).a =100//也是合法的
四、
temp :=&ueueQ{100,99.9}
temp即为ueueQ类型的指针
用结构体初始化另一个结构体
type ueueQ struct{
a int
b float32}type xml ueueQ //给ueueQ起别名*********funcmain(){var class1 = ueueQ{100,99.9}
class2 := xml{10,9.9}var class3 ueueQ = calss2 //这样是非法的,type xml 不能赋值给 type ueueQvar class3 =xml(class2)//合法var class3 =ueueQ(class1)//合法}
结构体工厂
这个东西是个什么意思呢?
比如C++中的类有构造函数,可以对对象进行初始化,但是go的结构体,可以使用结构体工厂“制造结构体”
type ueueQ struct{
a int
b int}func(w *ueueQ)NewQueue(_a,_b int)*ueueQ,e{
w.a=_a
w.b=_b
return w,true}
tnlp,val :=NewQueue(7,3)
这样在包外构建该类型结构体的时候,也很优雅了
make与new
切片、map、channel 可以用make
结构体可以用new,不能用make
自定义包中的结构体如何让外包使用
一、
type ExpStruct struct{
Mi1 int
Mf1 float32}
此结构体,外包既能用ExpStruct,也能访问结构体中的数据,因为都是大写的
二、结构体导出了,字段未导出
type ExpStruct struct{
mi1 int
mf1 float32}
此结构体,外包只能使用ExpStruct,而不能访问结构体内的数据,因为是小写,即私有
那么如何在包外使用呢?就是oop上的setter和getter方法了
func(p *ExpStruct )SetFirstName(newName float32){//间接的实现
p.mf1 = newName
}
package main
import"fmt"type innerS struct{
in1 int
in2 int}type outerS struct{
b int
c float32int// anonymous field
innerS //anonymous field}funcmain(){
outer :=new(outerS)
outer.b =6
outer.c =7.5
outer.int=60
outer.in1 =5
outer.in2 =10
fmt.Printf("outer.b is: %d\n", outer.b)
fmt.Printf("outer.c is: %f\n", outer.c)
fmt.Printf("outer.int is: %d\n", outer.int)
fmt.Printf("outer.in1 is: %d\n", outer.in1)
fmt.Printf("outer.in2 is: %d\n", outer.in2)// 使用结构体字面量
outer2 := outerS{6,7.5,60, innerS{5,10}}
fmt.Println("outer2 is:", outer2)}
可以得出结论:
在一个结构体中,对于每一种数据类型只能有一个匿名字段。【因为类型代表字段名字】
内嵌结构体的命名冲突问题
一、不同级命名冲突
type temp struct{
a int}type xnl struct{
a int
val temp
}var obj xnl
obj.a表示的xnl中的a
obj.val.a表示的是继承的temp中的a
二、同一级命令冲突
type temp1 struct{
a int}type temp2 struct{
a int}type xnl struct{
x1 temp1
x2 temp2
}var obj xnl
obj.a会发生错误,因为它不知道是哪一个结构体里面的a
只能obj.temp1.a或者obj.temp2.a这样使用
如果方法继承了,机制是如何的?
type baba struct{
b int}func(th *baba)add(){
fmt.Println("调用了爸爸")}type son struct{
s int
baba
}func(th *son)add(){//覆写了方法
fmt.Println("调用了儿子")}funcmain(){var xml son
xml.add()
xml.baba.add()}
输出:
调用了儿子
调用了爸爸
如果子类中没有和父类同名的方法,则直接可以通过子类实例调用父类方法
如何在类型中嵌入功能
子类继承父类的功能,该如何去使用它?
一、聚合(或组合):包含一个所需功能类型的具名字段
type Log struct{
msg string}func(th *Log)oop(){...}type Customer struct{
Name string
log *Log //字段直接具名,不在匿名}func(th *Customer)Log()*Log{return th.Log}var obj Customer
obj.Log().oop()//这样间接的调用
子类Customer在使用父类Log功能的时候,不是直接调用父类的方法,而是通过具名字段
二、内嵌:内嵌(匿名地)所需功能类型
type Log struct{
msg string}func(th *Log)oop(){...}type Customer struct{
Name string
Log
}var obj Customer
obj.Log.oop()//通过匿名字段调用父类方法
多重继承
一个继承多个,不在赘述
类型的 String() 方法和格式化描述符
一个结构体,如果该类型类型定义了 String() 方法。
那么,fmt.Print()、fmt.Printf()、fmt.Println()会自动的使用String()方法
type ueueQ struct{
a int
b int}func( th *ueueQ)String()string{return"("+ strconv.Itoa(tn.a)+"/"+ strconv.Itoa(tn.b)+")"}funcmain(){
v :=new(TwoInts)
v.a =12
v.b =10
fmt.Printf("two1 is: %v\n", v)
fmt.Println("two1 is:", v)
fmt.Printf("two1 is: %T\n", v) 格式化描述符 %T 会给出类型的完全规格
fmt.Printf("two1 is: %#v\n", v)%#v 会给出实例的完整输出
fmt.println(v)//这里会直接调用ueueQ的String()方法}
输出:
two1 is:(12/10)
two1 is:(12/10)
two1 is:*main.TwoInts 注意下
two1 is:&main.TwoInts{a:12, b:10} 注意下
不要再String()方法里面,直接打印该类型,
type TT float64func(t TT)String()string{return fmt.Sprintf("%v", t)//这样会造成递归调用,无限吃内存}
t.String()