Go语言的语言设计非常的简洁,因为,Go语言并没有面向对象的概念,因此Go语言中没有面向对象的一些概念,例如(封装、继承、多态,虚函数、构造函数,this指针等)
尽管Go语言中没有封装、继承、多态,但同样也可以实现相应的功能。
封装:通过方法进行实现
继承:通过匿名字段实现
多态:通过接口实现
方法
方法也是一种函数类型,本质上,一个方法则是一个和特殊类型关联的函数
type Int int
//a为接收者,Int为接收者的名字
func (a Int)add(b Int)Int{
return a+b
}
func main(){
var a Int = 3
res := a.add(2)
fmt.Println(res)
}
同时,可以通过方法为结构体变量赋值。
type Person struct{
Name string
Age int
}
func (P Person)PrintInfo(){
//...一些基本操作
}
我们可以通过函数为结构体进行赋值操作。
type Person struct{
Name string
Age int
}
func (P *Person)SetInfo(s string,i int){
P.Name = s
P.Age = i
}
func main(){
var p Person
(&p).SetInfo("bai",20)
fmt.Println(p.Name,p.Age)
}
方法类似于多了一个参数,我们可以将接受方法看成一个参数。
注意
- 自定义类型不能为指针类型
- 接收者类型不同,同名也不会出现错误。
匿名字段
type person struct{
Name string
Age int
}
type Student struct{
person //只有类型,没有具体名称
className string
}
上面的Student类中,包含person的匿名字段,相当于继承于person。
初始化方式:
- 顺序初始化
s1 := Student{person{"bai",20},"xiaan"}
- 指定成员初始化
s2 := Student{className:"xiaan"}
s3 := Student{person:person{Name:"bai"},className:"xiaan"}
结构体指针类型匿名字段
type person struct{
Name string
Age int
}
type Student struct{
*person //指针类型
className string
}
初始化操作
-
直接赋值
s1 := Student{&person{"bai",20},"xiaan"}
-
先初始化,在赋值
var s1 Student
s1.person = new (person)
s1.Name = "bai"
s1.Age = 20
s1.className = "xiaan"
接口
Go语言中使用接口实现多态的效果。
接口的定义:
type 接口名 interface{
接口声明
}
例如:HelloWorld接口的定义
type Hello interface{
HelloWorld() //只声明,不实现
}
HelloWorld接口的实现
//通过自定义类型实现接口
type Student struct{
name string
age int
}
func (s *Student)HelloWorld(){
fmt.Printf("Student [%s %d]",s.name,s.age)
}
//默认类型实现接口
type Int int
func (i *Int)HelloWorld(){
fmt.Printf("I")
}
HelloWorld接口的调用
//自定义类型调用接口
s := &Student{
"xiao",20}
var h Hello
h = s
h.HelloWorld()
//默认类型调用接口
var i Int
h = i
h.HelloWorld()
常见多态的实现方式
- 定义一个函数,函数的参数类型为接口类型
//多态:只有一个函数,实现不同功能
func Test(h Hello){
h.HelloWorld()
}
func main(){
s := &Student{
"xiao",20}
Test(s)
]
接口的继承
type Humaner interface{
Hello() //定义一个Hello接口
}
type Person interface{
Humaner //匿名字段,接口的继承
HelloWoeld(str string)
}
//自定义数据类型
type Student struct{
name string
age int
}
//Hello接口的实现
func (s *Student)Hello(){
fmt.Printf("name= %s age%d=",s.name,s.age)
}
//HelloWorld接口的实现
func (s *Student)HelloWorld(str string){
fmt.Printf("str name=%s age%d ",s.name,s.age)
}
//接口的调用
func main(){
var p Person
s := &Student{
"bai",20} //实例化一个结构体
p = s
p.Hello() //调用继承的Hello接口
p.HelloWoeld() //调用自身的HelloWorld接口
}
接口的转换
超级可以转换为子集,子集不能转换为超集。
var p Person //超集
var h Humaner //子集
p = h //错误
h = p //正确
空接口
空接口不包含任何方法,因此,所有的类型都可以实现空接口。
空接口可以存储任何类型的值
var v1 interface{
} = 1 //将int类型赋值给空接口
var v2 interface{
} = "abc" //将string类型赋值给空接口
空接口也可以作为函数的参数,表示该函数可以接收任意类型。常见的fmt函数就是一个空接口函数
类型查询
由于空接口函数可以接收任意类型的参数,因此需要类型查询。常见类型查询的办法为类型断言
//定义一个空接口切片
i := make([]interface{
},3)
i[0] = 1
i[1] = "abc“
i[2] = Student{"bai",20}
//if -- else类型断言
//for循环:index为下标,data为具体的值分别是i[0],i[1],i[2]
for index,data := range i{
//value为具体的值,ok为true时表示判断正确,ok为false表示判断错误
if value,ok := data.(int) == true{
}
}
//switch 类型断言
for index,data := range i{
switch value:= data.(type){
case int:
...
case string:
...
case struct:
...
}
}