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类型然后才为它定义方法,是因为不允许直接为内置类型定义方法。

最后更新于