接口的实现
如果接口类型只包含一个方法,那么这个类型的名字以er结尾。
golang中实现接口的方式:
• 结构体形式实现结构
type Duck interface{
Swim()
Quack()
}
type Person struct{}
func (p Person) Swim(){
fmt.Println("游泳")
}
func (p Person) Quack(){
fmt.Println("鸭子叫")
}
• 结构体指针实现接口
type Handler interface {
ServerHTTP(ResponseWriter, *Request)
}
type ServeMux struct {}
func (mux *ServeMux) ServeHTTP( w ResponseWriter, r *Request) {
// 具体的实现
}
• 函数实现接口
type Handler interface {
ServerHTTP(ResponseWriter, *Request)
}
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
// 具体的实现
}
探讨下调用接口的情况:
如下实现接口:
package main
import "fmt"
type Matcher interface {
Search(searchTerm string) (string, error)
}
// 实现这个接口
type rssMatcher struct{}
func (r rssMatcher) Search(searchTerm string) (string, error){
fmt.Println(searchTerm)
return searchTerm, nil
}
它的调用方式有4种:
func main() {
var dm0 rssMatcher
//指针来调用
dm1 :=new(rssMatcher)
dm1.Search("test1")
//值来调用
var dm2 rssMatcher
dm2.Search("test2")
// 将值传给接口
var dm4 Matcher = dm0
dm4.Search("test3")
// 将指针 传给接口
var dm5 Matcher = &dm0
dm5.Search("test4")
}
如果改成指针作为接收者:
package main
import "fmt"
type Matcher interface {
Search(searchTerm string) (string, error)
}
// 实现这个接口
type rssMatcher struct{}
func (r *rssMatcher) Search(searchTerm string) (string, error){
fmt.Println(searchTerm)
return searchTerm, nil
}
func main() {
var dm0 rssMatcher
//指针来调用
dm1 :=new(rssMatcher)
dm1.Search("test1")
//值来调用
var dm2 rssMatcher
dm2.Search("test2")
// 将值传给接口 Cannot use 'dm0' (type rssMatcher) as type Matcher Type does not implement 'Matcher' as 'Search' method has a pointer receiver
var dm4 Matcher = dm0
dm4.Search("test3")
// 将指针 传给接口
var dm5 Matcher = &dm0
dm5.Search("test4")
}
调用方式变成了三种, 其中将值赋值给接口的方式会编译出错。
现象:
- 如果用值作为方法的接收者,编译器会隐式的转换成指针去调用方法。这样无论传给接口类型的是值还是指针都没有问题。
但是如果用指针作为方法的接收者,在将值传给接口类型的时候,会提示该值没有实现这个接口。
总结:
- 赋值的时候类型不匹配,说明接口的接收者类型必须要小于等于定义的类型
- 假设指针为子类型,值的情况为父类型:
- 那么接收者定义为值就可以用指针和值来赋值。
- 那么接收者定义为指针就不能用值来赋值。