Comment on page

11 接口(Interface)

接口就是定义了一组方法的类型。
接口是对行为的抽象。
例如,标准库中定义了io.Reader接口:
type Reader interface {
Read(d []byte) (int, error)
}
绝大多数操作二进制数据流的函数(比如JSON解码器)都是把io.Reader作为数据来源。这样,我们就可以为物理文件、内存中的字节、网络连接等实现Reader接口,使json.Decode可以处理这些数据。
下面展示了如何定义和实现一个简单接口:
package main
import (
"fmt"
"strconv"
)
// Stringer就是一个接口,它里面只包含了1个函数
type Stringer interface {
String() string
}
// User结构体是准备用来实现Stringer接口的
type User struct {
Name string
}
func (u *User) String() string {
return u.Name
}
// 任何类型都可以实现某个接口。
// 这里我们创建一个int类型的别名,然后用它实现Stringer接口
type MyInt int
func (mi MyInt) String() string {
return strconv.Itoa(int(mi))
}
// printTypeAndString 函数接收一个接口。
// 's' 可以是任何实现了Stringer接口的类型的值。
func printTypeAndString(s Stringer) {
fmt.Printf("%T: %s\n", s, s)
}
func main() {
u := &User{Name: "John"}
printTypeAndString(u)
n := MyInt(5)
printTypeAndString(n)
}
上述代码的输出:
👉
点击此处
👈
亲自尝试执行代码。
*main.User: John
main.MyInt: 5
跟其他大多数语言都不同,Go的接口是被隐式实现的。
我们不需要显式地声明struct User要实现Stringer接口。
接口只可以包含方法,不可以包含数据。如果您想既复用方法又复用数据,请使用结构体嵌入
您只能在定义类型的包里面为该类型定义方法。我们刚才先定义了MyInt类型然后才为它定义方法,是因为不允许直接为内置类型定义方法。