# 11 接口(Interface)

接口就是定义了一组方法的类型。

接口是对行为的抽象。

例如，标准库中定义了`io.Reader`接口：

```go
type Reader interface {
    Read(d []byte) (int, error)
}
```

绝大多数操作二进制数据流的函数(比如JSON解码器)都是把`io.Reader`作为数据来源。这样，我们就可以为物理文件、内存中的字节、网络连接等实现`Reader`接口，使`json.Decode`可以处理这些数据。

下面展示了如何定义和实现一个简单接口：

```go
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)
}
```

上述代码的输出： :point\_right: [点击此处](https://play.golang.org/p/ba83kFxk4Yg) :point\_left: 亲自尝试执行代码。

```go
*main.User: John
main.MyInt: 5
```

跟其他大多数语言都不同，Go的接口是被隐式实现的。

我们不需要显式地声明`struct User`要实现`Stringer`接口。

接口只可以包含方法，不可以包含数据。如果您想既复用方法又复用数据，请使用[结构体嵌入](https://denglj.gitbook.io/essential-go/10-structs/composition-and-embedding)。

您只能在定义类型的包里面为该类型定义方法。我们刚才先定义了`MyInt`类型然后才为它定义方法，是因为不允许直接为内置类型定义方法。
