Golang 的接口实现

0x00 写在前面

golang 中的接口实现并非是显示的使用某个关键字(如 Java 中的 implements)来实现,而是隐式的实现——只要实现了接口中指定的所有方法,即视为实现了该接口。但是在接口实现上并非是简单的由类型本身来实现,毕竟在定义接口的时候也并没有指定 receiver 是否是类型本身,那就当然有可能是类型的指针。

0x01 方法

简单的复习一下方法,一切由 func 关键字开头的能够实现某种特定功能的代码块就叫做方法。方法可以包含方法签名、参数列表、返回列表、接收器,这些要素可以全部都有,也可以全部都没有(匿名内部无参无返回方法)。其中,接收者 receiver 可以分为:类型本身——调用时进行值传递;类型指针——调用时进行引用传递。虽然在调用方法时,golang 会自动的解引用,所以不管是声明在类型本身还是类型指针上的方法,都可以通过 typeT.funcName 的方式来进行调用(调用接口方法也一致)。

0x02 接口类型的实现

其实就方法的调用而言,实现接口的究竟是类型本身还是类型指针这个并无二致,得益于上述的 golang 自动解引用机制,都是通过具体的类型变量即可调用。但是具体实现接口的却存在实质上的区别。举个栗子:

...... code ......

// 声明一个接口类型
type testInterface interface {
	test1()
	test2()
}

// 自定义一个类型
type integer int 
type integer2 int

func testAssertion() {
    var ti testInterface
    _, ok1 := ti.(integer)
    _, ok2 := ti.(*integer)
    fmt.Printf("全部由类型本身实现,强制转换为类型本身:%v, 强制转换为类型指针: %v\n", ok1, ok2)
    
    _, ok1 = ti.(integer2) // 报错 integer2 does not implement testInterface (method test2 has pointer receiver)
    _, ok2 = ti.(*integer2)
    fmt.Printf("部分由类型指针实现,强制转换为类型本身:%v, 强制转换为类型指针: %v\n", ok1, ok2)
    
    _, ok1 = ti.(integer3) // 报错 integer3 does not implement testInterface (method test2 has pointer receiver)
    _, ok2 = ti.(*integer3) // 未报错,执行结果 ok2 = true
    fmt.Printf("全部由类型指针实现,强制转换为类型本身:%v, 强制转换为类型指针: %v\n", ok1, ok2)
}

// Demo1 接口的方法全由类型本身实现
func (in integer) test1() {}
func (in integer) test2() {}

// Demo2 接口的方法部分由类型指针实现
func (in integer2) test1() {}
func (in *integer2) test2() {}

// Demo3 接口的方法全部由类型指针实现
func (in integer3) test1() {}
func (in *integer3) test2() {}
...... code ......

0x03 接口的强制转换

从上述例子中不难看出,当且仅当类型本身实现了接口中所有的方法时,实现接口的才是类型本身;反之,当接口内方法存在由类型指针实现的情况,实现接口的便是类型指针了。同样的,不仅仅强转会出错,赋值也会出错,如下:

// 接上文中的数据类型

...... code ......

var ti testInterface

// 全由类型本身实现,正常赋值
var in integer
testInterface = in

// 部分由类型指针实现,报错 cannot use in (variable of type integer2) as testInterface value in assignment
var in2 integer2
testInterface = in2

// 全部由类型指针实现,报错 cannot use in (variable of type integer3) as testInterface value in assignment
var in2 integer3
testInterface = in3

...... code ......

究其原因当是:当类型本身实现了某个方法时,golang 会自动的为其生成类型指针为 receiver 的版本,这也就是为什么我们能够通过 类型指针 调用以 类型本身 为 receiver 的方法。反之则不然,golang 并不会自动的生成类型本身为 receiver 的版本,所以虽然我们能够通过 golang 本身的自动解引用机制调用 receiver 并非本身类型(指针与非指针)的方法,但接口并不会将没有完全实现接口内所有方法的 类型本身 视为该接口。

0x04 后记

本文是笔者学习过程中一点浅薄的见解,如有错误欢迎指出,并不胜感谢。
官方给出的解释更加的清晰易懂:
在这里插入图片描述

致谢 【精选】Go 学习笔记(71)— Go 接口 interface (接口定义、接口实现、接口调用、值接收者、指针接收者)_golang interface 指针_wohu007的博客-CSDN博客

Golang是一种编程语言,具备强大的接口特性。在Golang中,接口是一种规定了对象必须遵循的行为规范。通过接口,我们可以定义一组方法的集合,任何实现了这些方法的类型都被视为实现了该接口接口实现是指一个类型声明自己遵循了某个接口实现一个接口的类型,需要实现接口中定义的所有方法。实现接口的类型不需要显式声明实现了该接口,只要实现接口中定义的方法即可。这种方式称为隐式接口实现接口对象是指一个接口类型的变量或参数,可以指向满足该接口的任何具体类型的对象。通过接口对象,我们可以调用接口中定义的方法,而不需要关心具体对象是哪种类型。 使用接口的好处是可以将接口作为一个统一的契约,使得不同类型的对象可以通过实现相同的接口实现类型的替换和灵活的设计。接口可以实现代码的重用,并且松耦合,提高代码的可维护性和可测试性。 在实际应用中,我们可以先定义接口,然后根据接口的行为规范来编写具体类型的实现接口对象可以根据需要替换为不同的具体类型对象,实现了面向接口编程的思想。 总结来说,Golang中的接口实现是指类型声明自己遵循了某个接口实现接口中定义的方法。接口对象是指可以指向满足该接口的任何具体类型的对象。通过接口,我们可以实现代码的灵活和重用,使得不同类型的对象可以通过实现相同的接口来进行类型的替换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值