接口是golang最重要的特性之一,在Go中,接口interface其实和其他语言的接口意思没什么区别。interface理解其为一种类型的规范或者约定。一种类型是不是“实现”了一个接口呢?就看这种类型是不是实现了接口中定义的所有方法。接⼝是一个或多个方法签名的集合,任何非接口类型只要拥有与之对应的全部方法实现 (包括相同的名称、参数列表以及返回值。),就表示它"实现" 了该接口,无需显式在该类型上添加接口声明。
go的接口和定义
- 接口实现是隐式的,只需要实现里的全部方法(方法的参数和返回值类型要一致)
- 接口由使用者来定义
go接口使用:
调用者 :
// 使用者定义接口及接口内的方法
type Retriever interface {
Get(url string) string
}
// 使用者定义使用接口的方法
func download(r Retriever) string{
return r.Get("this is a get func")
}
实现者:
// 实现者定义一个类型
type MyRetriever struct {
Contents string
}
// 实现者实现接口内的get方法即可
func (r MyRetriever) Get(url string) string{
return r.Contents +","+ url
}
main
func main(){
var r Retriever
r = MyRetriever{"this is mytriever"}
fmt.Println(download(r))
}
在这个例子中,使用者定义了接口和接口中的方法,实现者不需要显示实现接口,只需要实现接口中的全部方法(就代表隐式地实现了接口)
- interface接口定义由使用者定义
- 使用者想使用这个接口的get方法
- 实现者完全不用管要实现哪个接口,只需要实现这个接口的方法即可
接口类型的判断
- type switch
- type assertion
interface类型有 interface.(type)的方式
switch v := r.(type) {
case MyRetriever:
fmt.Println(v.Contents)
}
//或者 显示转化 type assertion
myre := r.(MyRetriever)
fmt.Println(myre.Contents)
//或者严格版本的显示转化
if MyRetriever, ok := r.(MyRetriever); ok{
fmt.Println(MyRetriever.Contents)
}else {
fmt.Println("error")
}
接口的组合
- 接口的组合也是使用者定义,可以分开定义各个接口,也可以定义接口组合
- 实现者实现接口,不管是怎么定义的,只管实现接口的方法即可。
使用者
// 定义接口1
type Retriever interface {
Get(url string) string
}
// 定义接口2
type Poster interface {
Post(url string) string
}
// 定义接口3(接口1和接口2的组合,并且有自己的方法)
type RetrieverPoster interface {
Retriever
Poster
Connect(str string) string
}
// 下面就是对上面三个接口的调用,参数分别是接口对象
func download(r Retriever) string{
return r.Get("this is a get func")
}
func post(p Poster) string{
return p.Post("this is a post func")
}
func retrieverPoster(s RetrieverPoster) {
s.Get("this is a get func of retrieverPoster")
s.Post("this is a post func of retrieverPoster")
}
func main(){
// 使用1
var r Poster
r = MyRetriever{"this is mytriever"}
retrieverPoster(r) // error
post(r) // right
// 使用2
var re Retriever
re = MyRetriever{"this is mytriever"}
download(re)
// 使用3
rp := MyRetriever{"this is mytriever"}
retrieverPoster(rp) // right
download(rp) // right
}
实现者
//MyRetriever 实现了Retriever和Poster的接口,只需要实现这两个接口的方法即可
type MyRetriever struct {
Contents string
}
func (r MyRetriever) Get(url string) string{
fmt.Println(r.Contents +","+ url)
return r.Contents +","+ url
}
func (r MyRetriever) Post(url string) string{
fmt.Println(r.Contents +","+ url)
return r.Contents +","+ url
}
func (r MyRetriever) Connect(url string) string{
fmt.Println(r.Contents +","+ url)
return r.Contents +","+ url
}