长安链 DApp 开发必学 Go 11

153 阅读2分钟

这一章继续探索接口 interface

有的时候,我们需要根据接口 interface 的值类型来做不同的处理,这就需要有判断的能力。

go 提供了“类型断言”(type assertion)的写法:

t, ok := i.(T)

来看下官方给的例子:

package main

import "fmt"

func main() {
	var i interface{} = "hello"  // 定义一个空接口,赋值字符串 “hello”

	s := i.(string)              // 类型断言为字符串 string 类型
	fmt.Println(s)

	s, ok := i.(string)          // 加入ok变量,获得类型断言结果
	fmt.Println(s, ok)

	f, ok := i.(float64)         // 类型断言失败,会返回空值以及 false
	fmt.Println(f, ok)

	f = i.(float64) // panic     // 不适用ok变量,类型断言失败会直接报错
	fmt.Println(f)
}

接口 interface 类型断言也可以用 switch 关键字,正好也展示一下类型断言的实际代码演示:

package main

import "fmt"

func do(i interface{}) {
	switch v := i.(type) {                 // switch 关键词进行类型断言
	case int:
		fmt.Printf("Twice %v is %v\n", v, v*2)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v))
	default:
		fmt.Printf("I don't know about type %T!\n", v)
	}
}

func main() {
	do(21)
	do("hello")
	do(true)
}

我们已经学习了很多关于接口 interface 的知识,来看看具体怎么应用。

先来看看 go 源代码是怎么使用接口的,在 fmt 这个官方实现包里,定义了 Stringer 接口:

type Stringer interface {
    String() string
}

Stringer 接口定义了 String 方法,在使用 fmt 包进行打印的时候,实际上就是调用 String 方法。

通过自定义实现 String 方法,可以实现想要的打印结果:

package main

import "fmt"

type Person struct {                  // 定义 Person 结构体
	Name string
	Age  int
}

func (p Person) String() string {     // 自定义 String 方法
	return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
	a := Person{"Arthur Dent", 42}
	z := Person{"Zaphod Beeblebrox", 9001}
	fmt.Println(a, z)             // 调用 fmt 打印,实际上就是调用上面自定义的 String 方法
}

知道了 Stringer 接口,我们来实现一个打印 IP 地址的功能:

package main

import "fmt"

type IPAddr [4]byte

func (ip IPAddr) String() string {     // 打印 IP 地址
	return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
}

func main() {
	hosts := map[string]IPAddr{
		"loopback":  {127, 0, 0, 1},
		"googleDNS": {8, 8, 8, 8},
	}
	for name, ip := range hosts {
		fmt.Printf("%v: %v\n", name, ip)
	}
}

ok,这一章结束,我们就讲完了接口 interface。