先看golanger.com关于interface的说明
*Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here*
翻译下来就是: interfaces 用来指定一个object的的行为,如果该object能够执行该行为,这个接口就可以替代这个对象。
文档中举了一个例子: fmt包中的Fprintf方法
`func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)`
第一个参数是 io.Writer
看io.Writer的定义
type Writer interface {
Write(p []byte) (n int, err error)
}
就是说只要实现了Write方法的struct 都可以作为第一个参数传递给Fprintf。为了验证这个,我写了一段代码
package main
import (
"fmt"
)
type S struct {
b []byte
}
func (this *S) Write(p []byte) (n int, err error) {
this.b = p
return 0, nil
}
func main() {
s := new(S)
fmt.Fprintf(s, "abc")
}
果然如此这时候调用fmt.Fprintf方法就会吧"abc"输出到s中。
来查询下实现了该io.writer接口的对象有哪些:
bytes包里面的Buffer对象
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
m := b.grow(len(p))
return copy(b.buf[m:], p), nil
}
这里可以推测下对与byte类型数据,封装的其实是一个Buffer*,当调用fmt.Printf方法写近byte对象时候,会让Buffer实际上对需要写进去的数据进行操作。调用的b.grow方法可见该Buffer是动态分配的大小的。
下面是http包中对于response结构的Write方法实现
func (w *response) Write(data []byte) (n int, err error) {
if w.conn.hijacked() {
log.Print("http: response.Write on hijacked connection")
return 0, ErrHijacked
}
if !w.wroteHeader {
w.WriteHeader(StatusOK)
}
if len(data) == 0 {
return 0, nil
}
if !w.bodyAllowed() {
return 0, ErrBodyNotAllowed
}
w.written += int64(len(data)) // ignoring errors, for errorKludge
if w.contentLength != -1 && w.written > w.contentLength {
return 0, ErrContentLength
}
return w.w.Write(data)
}
这两个例子能够表现出来接口的适应能力,它可以代表实现某一个方法的所有结构。它可以作为一个形参来接受所有实现该接口的实参。
更多评论