先看程序:
func stringReader(){
reader:=strings.NewReader("This is a text message that used to test string reader.")
p:=make([]byte,4)
for{
n,err:=reader.Read(p)
if err!=nil{
if err==io.EOF{
fmt.Println("EOF",n)
break
}
fmt.Println(err)
os.Exit(1)
}
fmt.Println(n,string(p[:n]))
}
}
func main(){
stringReader()
}
输出:
4 This
4 is
4 a te
4 xt m
4 essa
4 ge t
4 hat
4 used
4 to
4 test
4 str
4 ing
4 read
3 er.
EOF 0
这个程序的strings.NewReader("This is a text message that used to test string reader."),返回一个*Reader的接口的指针,它就是接口的具体使用。
那么,接口到底是什么呢?
考虑一个代码片段:
func example(a){ //这里是伪代码
...
a.fun()
...
}
请问,对a.fun的调用,如何保证能够正确执行?显然,a对象必须有fun()方法才行。或者换一句话,为保证代码片段的正确执行,传入的对象必须具有该该代码段需要的方法。再换种说法,example函数需要一个具有fun方法的对象。(至于这个对象具体是什么,example函数并不care)。我们抽象一下:
我们需要定义一个这样的对象,它具有某些特定的方法,这个,就是interface的本质。
上面的代码片段可以改为:
type funInterface interface {
fun()
}
func example(a funInterface) { //这里是真代码了哦,呵呵
a.fun()
}
仔细观察上面的代码段,形式参数a,到底是什么具体类型的对象我们并不知道,但是go知道它是funInterface接口类型(注意接口类型对象实际是一个高级指针,如果没有指向具体对象,它是不能干活的),那么任何传入的对象,如果没有fun()方法的话,编译是没法通过的,这就满足了我们的要求。
嗯,现在您需要一个具体实现。
type funObj struct{}
func(*funObj) fun(){
fmt.Println("I am a funny object.")
}
这个具体实现有什么特点? 它不需要显式指定接口,换句话说,你在实现具体对象的时候,完全不依赖任何定义的接口。只有当你把定义的对象赋值给接口对象的时候,go才检查,如果赋值的对象不符合接口,go就编译报错。
嗯,具体如何使用呢?我们给出完整程序:
type funInterface interface {
fun()
}
func example(a funInterface) { //这里是真代码了哦,呵呵
a.fun()
}
type funObj struct{}
func(*funObj) fun(){
fmt.Println("I am a funny object.")
}
func main() {
example(&funobj)
}
运行结果:
I am a funny object.
这就是golang接口的精华。