很多编程语言都提供了接口,Golang接口最大的特点是它可以不必显式定义,只要一个类型实现了某个接口定义的所有方法,那它就实现了这个接口。

C#语言实现接口的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public interface IMyInterface
{
    void MyInterfaceFunc();
}

public class MyClass : IMyInterface
{
    void IMyInterface.MyInterfaceFunc()
    {
        //some code
    }
}

Golang中实现接口的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
type IMyInterface interface {
	MyInterfaceFunc()
}

type MyClass struct {
}

func (p MyClass) MyInterfaceFunc() {
	//some code
}

func main() {
	var mc MyClass
	var imc IMyInterface = mc
	imc.MyInterfaceFunc()
}

可以看到在C#中我们需要显示指定类MyClass实现了接口IMyInterface,而在Golang中我们只要为MyClass绑定接口定义的方法,就相当于实现了这个接口。

接口的组合

有时候我们需要在接口中包含其他接口定义的方法,C#的做法是通过接口之间的继承:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface IMyInterface
{
    void MyInterfaceFunc();
}

public interface IMyInterface2 : IMyInterface
{
    void MyInterfaceFunc2();
}

public class MyClass : IMyInterface2
{
    public void MyInterfaceFunc()
    {
        //some code
    }

    public void MyInterfaceFunc2()
    {
        //some code
    }
}

Golang通过嵌套:

 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
type IMyInterface interface {
	MyInterfaceFunc()
}

type IMyInterface2 interface {
	IMyInterface
	MyInterfaceFunc2()
}

type MyClass struct {
}

func (p MyClass) MyInterfaceFunc() {
	//some code
}

func (p MyClass) MyInterfaceFunc2() {
	//some code
}

func main() {
	var mc MyClass
	var imc2 IMyInterface2 = mc
	imc2.MyInterfaceFunc2()
}

接口与指针

注意在为类型定义方法的时候有两种情况:为类型本身定义和为类型对应的指针定义。尽管在调用上由于语法糖的作用它们区别不是很明显,但是对应接口来说,为类型*MyClass定义的方法并不属于类型MyClass

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func (p *MyClass) MyInterfaceFunc() {
	//some code
}

func (p MyClass) MyInterfaceFunc2() {
	//some code
}

func main() {
	var mc MyClass
	//var imc2 IMyInterface2 = mc //compile error
    var imc2 IMyInterface2 = &mc // ok
}

接口的比较

当两个接口均为nil或者当它们的动态类型可以比较并且动态值满足相等比较时,这两个接口相等。

需要注意对接口进行相等比较并不总是安全的,如果接口的动态类型不可进行比较,会引发panic。

空接口

interface{}没有定义任何方法的接口,可以用来表示任何类型的值。

类型断言

两种情况

1
2
3
4
5
6
//如果i的动态值是Type类型,断言成功,返回i的动态值,否则引发panic
var v Type = i.(Type)
//如果i的动态值满足InterfaceType,断言成功,返回InterfaceType类型接口,否则引发panic
var v2 InterfaceType = i.(InterfaceType)
//如果i的动态值满足InterfaceType,断言成功,返回InterfaceType类型接口和true,否则返回nil, false
v3, ok := i.(InterfaceType)
 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
type IMyInterface interface {
	MyInterfaceFunc()
}

type IMyInterface2 interface {
	IMyInterface
	MyInterfaceFunc2()
}

type IMyInterface3 interface {
	IMyInterface2
	MyInterfaceFunc3()
}

type MyClass struct {
}

func (p MyClass) MyInterfaceFunc() {
	//some code
}

func (p MyClass) MyInterfaceFunc2() {
	//some code
}

func main() {

	var mc MyClass
	var ni interface{} = mc
	var mci_1 IMyInterface = ni.(IMyInterface) //ok
	mci_1.MyInterfaceFunc()
	var mci_2 IMyInterface2 = ni.(IMyInterface2) //ok
	mci_2.MyInterfaceFunc2()
	//var mci_3 IMyInterface3 = ni.(IMyInterface3)//panic
	//mci_3.MyInterfaceFunc3()
	mci_3, ok := ni.(IMyInterface3) //nil, false
	if ok {
		mci_3.MyInterfaceFunc3()
	}

}

BGM