golang (08) Interface Description

Original link  http://www.limerence2017.com/2019/09/12/golang13/#more

 

Interface Overview

golang the interface is a common data structure, the interface can achieve like functionality. What is it like?
Such as sparrows fly, eagles fly, they are birds, birds have wings and can fly. Aircraft can also fly
the plane is like a bird, like bird, so we can say that the airplane, balloon, a fly can fly like a bird.
But they are not a bird, then compare inherited relations, Eagles inherited from birds, it can fly, but he is a bird.
Look at an interface definition

1
2
3
type Bird interface {
Fly() string
}

 

Bird defines a type of interface, an internal life Fly method, the parameter is empty, the return value string.
Struct different methods and interface declarations, method interfaces written in the interface, and can not contain func and implementation.
In addition the internal interface can not declare member variables.
Here to achieve butterflies and aircraft category, achieving like-bird features. Fly like a bird.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Plane struct {
name string
}

func (p *Plane) Fly() string {
fmt.Println(p.name, " can fly like a bird")
return p.name
}

type Butterfly struct {
name string
}

func (bf *Butterfly) Fly() string {
fmt.Println(bf.name, " can fly like a bird")
return bf.name
}

 

Butterfly class and implements Plane, Fly and implements methods. Then the aircraft and butterflies can fly like a bird.
We call the main function

1
2
3
4
5
   pl := &Plane{name: "plane"}
pl.Fly()

bf := &Butterfly{name: "butterfly"}
bf.Fly()

 

Output follows

1
2
plane  can fly like a bird
butterfly can fly like a bird

 

Some people may ask, implemented separately Plane and Butterfly does not like, and why Bird something to do with it?
Because the interface as a function parameter, can accept different types of arguments, so long as the method argument implements the interface,
you can achieve a dynamic method call a different argument.

1
2
3
func FlyLikeBird(bird Bird) {
bird.Fly()
}

 

Let's call the above function in the main function, passing different arguments

1
2
   FlyLikeBird(pl)
FlyLikeBird(bf)

 

Output follows

1
2
plane  can fly like a bird
butterfly can fly like a bird

 

This is to achieve a dynamic call. Somewhat similar to C ++ polymorphism, but not through inheritance golang achieve this effect,
as long as the structure of the interface implements methods can be converted to the interface type.
golang This implementation mechanism broke through Java, C ++ and other traditional static languages Show Inherited defects.

Interface type conversion and determination

If a struct type implements the interface method, can be assigned to the corresponding interface types, the interface may be converted into the same type struct types.
We write a function, by which the bird internal function of the interface into a different type, so that incoming print specific type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func GetFlyType(bird Bird) {
_, ok := bird.(*Butterfly)
if ok {
fmt.Println("type is *butterfly")
return
}

_, ok = bird.(*Plane)
if ok {
fmt.Println("type is *Plane")
return
}

fmt.Println("unknown type")
}

 

main function calls

1
2
3
4
5
6
func main() {
pl := &Plane{name: "plane"}
bf := &Butterfly{name: "butterfly"}
GetFlyType(pl)
GetFlyType(bf)
}

 

Output follows

1
2
type is *Plane
type is *butterfly

 

看得出来接口也是可以转化为struct的。
结构体变量, bool类型:=接口类型.(结构体类型)
bool类型为false说明不能转化,true则能转化。

万能接口interface{}

golang 提供了万能接口, 类型为interface{}, 任何具体的结构体类型都能转化为该类型。我们将之前判断类型的例子
稍作修改。定义Human类和Human的Walk方法,然后实现另一个判断函数,参数为interface{}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
type Human struct {
}

func (*Human) Walk() {

}

func GetFlyType2(inter interface{}) {
_, ok := inter.(*Butterfly)
if ok {
fmt.Println("type is *butterfly")
return
}

_, ok = inter.(*Plane)
if ok {
fmt.Println("type is *Plane")
return
}
_, ok = inter.(*Human)
if ok {
fmt.Println("type is *Human")
return
}
fmt.Println("unknown type")
}

 

在main函数中调用,我们看看结果

1
2
3
4
5
6
7
8
func main() {
pl := &Plane{name: "plane"}
bf := &Butterfly{name: "butterfly"}
hu := &Human{}
GetFlyType2(pl)
GetFlyType2(bf)
GetFlyType2(hu)
}

 

看到输出

1
2
3
type is *Plane
type is *butterfly
type is *Human

 

.(type)判断具体类型

接口还提供了一个功能,通过.(type)返回具体类型,但是.(type)只能用在switch中。
我们实现另一个版本的类型判断

1
2
3
4
5
6
7
8
9
10
11
12
func GetFlyType3(inter interface{}) {
switch inter.(type) {
case *Butterfly:
fmt.Println("type is *Butterfly")
case *Plane:
fmt.Println("type is *Plane")
case *Human:
fmt.Println("type is *Human")
default:
fmt.Println("unknown type ")
}
}

 

main函数中调用这个函数

1
2
3
   GetFlyType3(pl)
GetFlyType3(bf)
GetFlyType3(hu)

 

输出结果如下

1
2
3
type is *Plane
type is *Butterfly
type is *Human

 

所以.(type)也实现了类型转换

这样接口基础都介绍完毕了,下一篇介绍接口内部实现和剖析。
感谢关注我的公众号
wxgzh.jpg

Guess you like

Origin www.cnblogs.com/secondtonone1/p/11571886.html