接口的实现
如果接口类型只包含一个方法,那么这个类型的名字以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 mainimport "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 rssMatcherdm2.Search("test2")// 将值传给接口var dm4 Matcher = dm0dm4.Search("test3")// 将指针 传给接口var dm5 Matcher = &dm0dm5.Search("test4")
}
如果改成指针作为接收者:
package mainimport "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 rssMatcherdm2.Search("test2")// 将值传给接口 Cannot use 'dm0' (type rssMatcher) as type Matcher Type does not implement 'Matcher' as 'Search' method has a pointer receivervar dm4 Matcher = dm0dm4.Search("test3")// 将指针 传给接口var dm5 Matcher = &dm0dm5.Search("test4")
}
调用方式变成了三种, 其中将值赋值给接口的方式会编译出错。
现象:
- 如果用值作为方法的接收者,编译器会隐式的转换成指针去调用方法。这样无论传给接口类型的是值还是指针都没有问题。
但是如果用指针作为方法的接收者,在将值传给接口类型的时候,会提示该值没有实现这个接口。
总结:
- 赋值的时候类型不匹配,说明接口的接收者类型必须要小于等于定义的类型
- 假设指针为子类型,值的情况为父类型:
- 那么接收者定义为值就可以用指针和值来赋值。
- 那么接收者定义为指针就不能用值来赋值。