1. 结构体
- go中没有class这个概念,但有struct
- 结构体的所有字段在内存中是连续的
- 结构体类型与结构体类型之间也可以相互转换,但是转换需要有完全相同的字段
- 名字,个数,类型
type A struct{
Num int
}
type B struct{
Num int
}
var a A
var b B
a=A(b)
1.1 结构体的声明
type 结构体名称 struct{
field1 type
filed2 type
}
1.2 结构体的使用
- 方式1
p1:=Person{"mary",20}
fmt.Println(p1)
p2:=Person{
name:"zhangsan",
age:19,
}
- 方式2
var p1 *Person=new(Person)
// go中指针可以用.
/**
对于指针p1,go的设计者,为了操作方便,当使用时p1.Name="李四",
底层自动会转换为(*p1).Name="李四"
*/
p1.Name="李四"
- 方式3
var p1 *Person=&Person{}
1.3 声明时加上tag(用于序列化)
type Monster struct{
Name string `json:"name"`
Age int `json:"age"`
Skill string `json:"skill"`
}
monster :=Monster{"牛魔王",200,"芭蕉扇。。"}
jsonStr,err:=json.Marshal(monster)
if err!=nill{
处理锁雾
}
fmt.Println("jsonStr",string(jsonStr))
- 私有字段好像不能被序列化
1.4 给结构体添加方法
- 在结构体外添加
func (receiver type) methodName(参数列表) (返回值列表){
方法体
return 返回值
}
type A struct{
Num int
}
func (a A) test(){
fmt.Println(a.Num)
}
var a A
a.Num=10
a.test()
- go中的方法作用在指定数据类型上的,因此自定义数据类型都可以有方法
- 而且不仅仅是struct,比如int,float32等都可以有方法
- 方法首字母小写,只能本包访问,方法首字母大写,其他包也可以访问
- 如果一个类型实现了String()这个方法,那么fmt.Println默认会调用这个变量的String()进行输出
- 通过一个变量调用方法时,其调用机制和函数一样,不一样的是,变量调用方法时,该变量本身也会作为一个参数传递到方法
- 如果是值类型则进行值拷贝
- 如果是引用类型则进行引用拷贝
1.5 方法与函数的区别
调用方式不一样
- 函数:函数名(实参列表)
- 方法:变量.方法名(实参列表)
普通函数,接受者为值类型时,不能将指针类型的数据直接传递,反之亦然
但对于方法,它只看接受者的类型,你可以传值类型,也可以传引用类型,但在方法里都是按照接受者的类型来看待
1.6 工厂模式向其他包提供私有结构体
package model
type student struct{
Name string
Score float64
}
func NewStudent(n string,s float64) *student{
return &student{
Name:n,
Score:s,
}
}
//其他包中
var stu=model.NewStudent("tom~~",99.2)
2. 面向对象
2.1 封装
- 对结构体中的属性进行封装
type person struct{
Name string
age int
sal float64
}
func NewPerson(name string) *person{
return &person{
Name:name,
}
}
func (p *person) SetAge(age int){
p.age=age
}
func (p *person) GetAge() int{
return p.age
}
func (p *person) SetSal(sal float64){
p.sal=sal
}
func (p *person) GetSal() float64{
return p.sal
}
// 其他包
p:=model.NewPerson("smith")
p.SetAge(18)
p.SetSal(500)
fmt.Println(p)
2.2 继承
type Goods struct{
Name string
Price int
}
type Book struct{
Goods // 嵌套匿名结构体就是继承
Writer string
}
- 结构体可以使用嵌套匿名结构体所有的字段和方法(无论首字母是否大小写)
- 结构体中的匿名字段还可以是基本数据类型,但不能有多个同一基本数据类型的匿名字段
type Monster struct{
Name string
Age int
}
type E struct{
Monster
int
n int
}
var e E
e.Name="张三"
e.Age=11
e.int=20
e.n=40
2.2.1 创建结构体给继承字段也赋值
type Goods struct{
Name string
Price float64
}
type Brand struct{
Name string
Address string
}
type TV struct{
Goods
Brand
}
type Tv1 struct{
*Goods
*Brand
}
tv:=TV{Goods{"电视机",500.9},Brand{"海尔","山东"},}
tv1:=TV1{
&Goods{
Name:"电视机",
Price:100.2,
},
&Brand{
Name:"长虹",
Address:"四川"
},
}
2.3 接口
2.3.1 声明接口
type 接口名 interface{
method1(参数列表) 返回值列表
...
}
- go语言中一个结构体(变量)不需要显示地实现接口
- 只要一个变量,含有该接口类型中的所有方法,那么这个变量就实现了这个接口
type Usb interface{
Start()
}
type Phone struct{
}
func (p Phone) Start(){
fmt.Println("手机start")
}
func Working(usb Usb){
usb.Start()
}
func main(){
phone :=Phone{}
Working(phone)
}
2.3.2 接口可以继承其他接口
type BInterface interface{
test1()
}
type CInterface interface{
test2()
}
type AInterface interface{
BInterface
CInterface
test3()
}
- 所有类型都实现了空接口
2.4 多态
2.4.1 多态参数
- 函数的形参是接口,调用时传入的实参是接口的实现
2.4.1 多态数组
- 数组是接口数组,存入的时候存入接口的实现
type Usb interface{}
var arr [3]Usb
arr[0]=1
arr[1]=99.1
arr[2]="string"
2.4.2 类型断言
接口变量.(类型)
type Usb interface{}
var a Usb
a="hello world"
str,ok :=a.(string)