35

Golang学习笔记之接口(interface)

 5 years ago
source link: https://studygolang.com/articles/16983?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

接⼝是⼀个或多个⽅法签名的集合,任何类型的⽅法集中只要拥有与之对应的全部⽅法,就表⽰它 "实现" 了该接⼝。

所谓对应⽅法,是指有相同名称、参数列表 (不包括参数名) 以及返回值。当然,该类型还可以有其他⽅法。

• 接⼝命名习惯以 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()
}

五、标准库中的常用接口

标准库文档

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
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK