接是个或多个法签名的集合, 任何类型的法集中只要拥有与之对应的全部法, 就表它 "实现" 了该接.
所谓对应法, 是指有相同名称, 参数列表 (不包括参数名) 以及返回值. 当然, 该类型还可以有其他法.
• 接命名习惯以 er 结尾, 结构体.
• 接只有法签名, 没有实现.
• 接没有数据字段.
• 可在接中嵌其他接.
• 类型可实现多个接.
• 引用类型
• 实现接口不需要显式的声明, 只需实现相应方法即可
• 多个类型可以实现同一个接口, 一个类型可以实现多个接口, 实现了某个接口的类型, 还可以有其它的方法.
• 接口的 0 值是 nil.
一, 接口定义
- type Namer interface {
- method1(param_list) return_list
- method2(param_list) return_list
- ...
- }
- demo
- package main
- import (
- "fmt"
- )
- //Phone 定义接口
- type Phone interface {
- // 接口里面的方法
- call()
- }
- type NokiaPhone struct {
- }
- // 结构体 NokiaPhone 实现了接口里面的方法
- func (nokiaPhone NokiaPhone) call() {
- fmt.Println("I am Nokia, I can call you!")
- }
- type iPhone struct {
- }
- //iPhone 实现了接口里面的方法
- func (iPhone iPhone) call() {
- fmt.Println("I am iPhone, I can call you!")
- }
- func main() {
- var phone Phone
- // 声明结构体
- phone = new(NokiaPhone)
- phone.call()
- phone = new(iPhone)
- phone.call()
- }
二, 空接 interface{} 没有任何法签名, 也就意味着任何类型都实现了空接. 其作类似向对象语中的根对象 object.
- package main
- import "fmt"
- func describe(v interface{}) {
- fmt.Printf("%T: %v\n", v, v)
- }
- func main() {
- describe(1)
- describe("Hello, World!")
- describe(8.88)
- }
输出
- int: 1
- string: Hello, World!
- float64: 8.88
三, 提取类型
利类型推断, 可判断接对象是否某个具体的接或类型.
i.(T)可以显示的来获取接口的某一种类型, i 的实际类型 T 的值的语法.
v, ok := i.(T)
如果 i 的具体类型是 T, 则 v 将具有 i 的实际值, ok 为 true. 否则 ok 为 false,v 为 T 类型对应的 0 值
- demo
- package main
- import "fmt"
- func findType(i interface{}) {
- switch i.(type) {
- case string:
- fmt.Printf("I am a string and my value is %s\n", i.(string))
- case int:
- fmt.Printf("I am an int and my value is %d\n", i.(int))
- case float64:
- fmt.Printf("I am an float64 and my value is %f\n", i.(float64))
- default:
- fmt.Printf("Unknown type I am an %T\n",i)
- }
- }
- func main() {
- findType(1)
- findType("Hello, World!")
- findType(8.88)
- findType('s')
- }
输出
- I am an int and my value is 1
- I am a string and my value is Hello, World!
- I am an float64 and my value is 8.880000
- Unknown type I am an int32
四, 接口嵌套
一个接口可以包含一个或多个其他的接口, 这相当于直接将这些内嵌接口的方法列举在外层接口中一样. 但是在接口内不能内嵌结构体, 编译会出错.
- type Stringer interface {
- String() string
- }
- type Printer interface {
- Stringer // 接嵌.
- Print()
- }
- type Person struct {
- id int
- name string
- }
- func (p *Person) String() string {
- return fmt.Sprintf("user %d, %s", p.id, p.name)
- }
- func (p *Person) Print() {
- fmt.Println(p.String())
- }
- func main() {
- var t Printer = &Person{1, "Tom"} //*Person 法集包含 String, Print.
- t.Print()
- }
五, 标准库中的常用接口
标准库文档 https://studygolang.com/pkgdoc
io.Reader 和 io.Writer
- type Reader
- type Reader interface {
- Read(p []byte) (n int, err error)
- }
Read 方法读取 len(p)字节数据写入 p. 它返回写入的字节数和遇到的任何错误.
- type Writer
- type Writer interface {
- Write(p []byte) (n int, err error)
- }
Writer 接口用于包装基本的写入方法. Write 方法 len(p) 字节数据从 p 写入底层的数据流.
类似的实现了 Writer 接口的对象有: os.Stdout, os.Stderr, os.File 等等. 可以使用 Write 方法向其中写入数据.
当一个类型包含 (内嵌) 另一个类型 (实现了一个或多个接口) 的指针时, 这个类型就可以使用 (另一个类型) 所有的接口方法.
类型可以通过继承多个接口来提供像 多重继承 一样的特性:
- type ReaderWriter struct {
- *io.Reader
- *io.Writer
- }
来源: http://www.jianshu.com/p/c10c79ddb828