目录

关于Go Interface的见解

可能有部分童鞋对于Go的interface不是很了解,本文通过几个例子,来阐述什么是interface,它如何实现,有什么作用。

言归正传,首先我们来看看interface的定义:Go语言中的接口(interface)是一种类型,只包含方法声明,没有实现。任何类型的对象,只要它实现了接口中的所有方法,就表示它实现了该接口。

interface的定义

1
2
3
4
type Person interface {
	Area()
	Eat()
}

我们定义了一个名为Person的interface,里面包含了Area和Eat两个方法。

interface的实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
type Person interface {
	Area()
	Eat()
}

type GuangDong struct {
    Name string
    Hobby string
}

func (gd GuangDong) Area () {
    fmt.Println("这是个广东人")
}

func (gd GuangDong) Eat() {
    fmt.Println("喜欢吃白切鸡")
}

我们再定义一个名为GuangDong的struct,并且根据interface中定义的方法名,创建对应的方法(注意方法名要一致)。如此,我们就可以说GuangDong实现了Person。 调用方式如下:

1
2
3
4
5
6
7
8
func TestInterFace(t *testing.T) {
	var person Person = GuangDong{
		Name:  "广东",
		Hobby: "清淡",
	}
	person.Area()
	person.Eat()
}

interface的作用

实现多态

那么问题来了,在调用上我们为何不直接用GuangDong这个对象来调用对应的方法,为何还要通过Person来调用?如此,我们再增加一个对象SiChuang:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
type SiChuang struct {
	Name string
	Hobby string
}

func (sc SiChuang) Area () {
	fmt.Println("这是个四川人")
}

func (sc SiChuang) Eat() {
	fmt.Println("喜欢吃麻婆豆腐")
}

到这里,学过面向对象编程的同学可能就知道了,这玩意就是多态的实现,为不同类型的对象提供统一的接口。

扩展

比较常用的实际应用有以下几种:

同一对象实现不同接口

根据上面的例子,我们再添加一个interface类型的City和GuangDong的方法:

1
2
3
4
5
6
7
8
type City interface {
	Area()
	Weather()
}

func (gd GuangDong) Weather()  {
    fmt.Println("广东天气一天四季")
}

调用方式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func TestInterFace(t *testing.T) {
	var person Person = GuangDong{
		Name:  "广东",
		Hobby: "清淡",
	}
	person.Area()
	person.Eat()
	
	var city City= GuangDong{
        Name:  "广东",
        Hobby: "清淡",
	}
	city.Area()
	city.Weather()
}

如此,GuangDong实现了Person和City。

功能扩展

接下来我们再来看看功能扩展,还是接着上面的例子,我们创建一个新的方法,里面传入Person类型的参数:

1
2
3
4
5
func AfterEat(person Person)  {
	person.Area()
	person.Eat()
	fmt.Println("吃完饭啦")
}

调用方式如下:

1
2
3
4
5
6
7
8
9
func TestInterFace(t *testing.T) {
	var person Person = GuangDong{
		Name:  "广东",
		Hobby: "清淡",
	}
	person.Area()
	person.Eat()
	AfterEat(person)
}

再举一个开发中比较常见的例子,有这么一个系统,在运行过程中需要调用A、B、C三个厂家的接口,需求如下:

  • A厂家需要在header传入auth参数,作为认证,并通过form表单提交数据。
  • B厂家需要传入json格式的参数。
  • C厂家需要传入json格式的参数,并通过AES的方式进行加密。
  • 所有厂家的返回数据需要进行统一处理后,返回给前端。
  • 需要把厂家操作进行封装,供其它后端同事在业务中进行调用。

通过这个需求的描述,我们可以这么做:

  • 定义一个interface类型的对象AppHttp,里面包含三个方法Header()、Post()、GetData(),分别用来设置header,封装并发送数据,获取数据。
  • 定义A、B、C三个厂家的对象ClientA、ClientB、ClientC,并实现interface中的方法。
  • 创建一个方法ReturnData,里面传入AppHttp类型的参数,对获取到的数据做格式化处理。
  • 如此一来,其它同事调用是只要关注AppHttp,直接调用对应的方法,不用关注ClientA、ClientB、ClientC具体是如何实现对应方法的。

这个例子的代码我就不放来,就当给各位练练手。

interface总结

  1. 实现多态性:通过接口,可以将不同类型的对象视为同一类型,从而在同一接口下使用不同的对象。
  2. 提供抽象层:接口定义了对象的行为,而不关心具体的实现细节。这使得代码的实现与接口分离,使代码更加灵活和可扩展。
  3. 促进代码复用:通过接口,可以定义一组公共方法,不同类型的对象可以共享这些方法,从而减少重复代码。
  4. 实现依赖倒置原则:接口定义了对象的行为,使得对象之间通过接口进行交互,而不是直接依赖具体的实现类,从而实现了依赖倒置原则。
  5. 提供标准化的编程规范:接口提供了一种标准化的编程规范,使得不同开发者可以按照接口定义的方式进行开发,提高代码的可读性和可维护性。
  6. 需要注意的是,在Go中,接口是隐式实现的,也就是说不需要显式地声明实现了某个接口,只需要实现了接口中定义的方法,就被认为是实现了该接口。这种设计使得接口的使用更加灵活和方便。