python
中的鸭子类型
def duck_run(duck):
duck.run()
与python
类似,go
语言中也有鸭子类型。
在go
语言中接口的类型是interface
type Retriever interface {
Get(url string) string
}
接着我们穿件包retriever
,然后在包中实现Retriever
type Retriever struct {
Contents string
}
func (r Retriever) Get(url string) string {
return r.Contents
}
接着就可以定义鸭子类型
func download(r Retriever) string {
return r.Get("www.baidu.com")
}
接口变量里面包含了实现者的类型
和实现者的指针
。
var r Retriever
r = retriever.Retriever{}
fmt.Printf("%T %v\n", r, r) //retriever.Retriever {}
我们可以通过switch type
判断接口类型,有点类似于cpp
中的typeid
switch v := r.(type) {
case retriever.Retriever:
fmt.Println("Contents: ", v.Contents)
}
也可以使用type assertion
取出接口中的具体类型
t := r.(retriever.Retriever) //r.(type)
interface {}
表示任意类型,通过这个我们可以实现泛型编程。
type Queue []interface{}
func (q *Queue) Push(v interface{}) {
*q = append(*q, v)
}
当然我们也可以写出相应的偏特化
func (q *Queue) Push(v int) { //只能Push int类型
*q = append(*q, v)
}
我们也可以在函数体内实现偏特化
func (q *Queue) Push(v interface{}) {
*q = append(*q, v.(int))
}
前者如果push
其他类型会出现编译错误,而后者是运行时出错。
第一个是Stringer
,类似于cpp
中的operator<<
运算符重载
func (r *Retriever) String() string {
return fmt.Sprintf("{test%s}", r.Contents)
}
第二个就是Reader
、Writer
func printContents(reader io.Reader) {
}
对文件的抽象。