Go语言的接口应该如何理解呢?它和Java等其他语言的区别在哪里呢?
答:其实Go语言的接口和其他一些面向对象编程的语言一样,都是抽象方法的一个集合,不同点在于接口的实现和变量赋值。
接口的实现:与其他语言相比,GO中的接口实现并不需要显示的声明!
只要一个类型中包含有某一接口的全部方法,并且这些对应方法的命名、传入参数和返回类型都完全匹配,那么该类型就可以当做此接口的实现,不需要额外声明。
type shaper interface {
area() float64
}
type circle struct {
radius float64
}
func (c *circle) area() float64{
return math.Pi * c.radius * c.radius
}
func main() {
circleA := circle{radius:10}
var shaperA shaper
shaperA = &circleA //对变量进行声明
var shaperB shaper
shaperB = new(circle)
fmt.Println("圆A的面积是",shaperA.area())
fmt.Println("圆B的面积为",shaperB.area())
}
结果为:
圆A的面积是 314.1592653589793
圆B的面积为 0
从示例可以看出来其实接口类型的变量本质上就是类似于指针。
实际上,接口类型的变量是一个复合数据结构:
第一部分指向接口的接受者,另一部分指向方法指针表。
对接口变量进行赋值:实际上会把实现该接口的类型的变量赋值给接受者,而方法指针表会获得指向具体实现的方法的指针;
这样程序在运行的过程中就知道某个接口类型的变量的方法的具体实现。接口是隐式的满足匹配的。
多种类型可以实现同一个接口,实现了一个接口的某个类型还可以有另外的方法,可以实现多个接口;
注意:如果接口或者接口中的方法声明是不可以导出的,则该接口方法无法被其他包中的类型所实现;
一些错误的接口实现:
1、没有完全实现接口所定义的方法;
type shaper interface {
area() float64
perimeter() float64
}
type circle struct {
radius float64
}
func (c *circle) area() float64{
return math.Pi * c.radius * c.radius
}
func main() {
circleA := circle{radius:10}
var shaperA shaper
shaperA = &circleA //错误!因为circle没有实现perimeter方法
}
2、用某一类型的变量直接对接口进行赋值;
circleA := circle{radius:10}
var shaperA shaper
/**不可以直接将变量赋值给接口变量,在Java中这么做是没有问题的,
但是在Go中因为接口类型的变量是一个类似与指针的东西,所以不能直接赋值;*/
shaperA = circleA
3、对不同包中具有不可导出方法 的接口进行实现;
空接口:
- 空接口就是没有任何方法的接口,所以实现它们不需要任何的要求。因此一个空接口变量可以被任意赋值,从而指向任何类型的对象。
- 空接口的概念接近与Java中的object,即所有对象的基类。空接口变量可以指向基本类型,比如int、指针等等;
- 空接口可以被赋予任意类型的值,它的实际应用就是标准库fmt里的Printf()函数和Println()函数,通过配合使用空接口和类型查询,能够实现可接受任意对象实例并进行处理的函数;
个人github:https://github.com/SpecialAll