GO成神之路:接口interface|Go主题月

1,009 阅读2分钟

接口interface

接口是一组方法签名,所有实现了该签名的子类都可以赋值给这个接口变量。

go中有两种接口的使用场景:1. 用作类型签名,2. 空接口(无方法签名)

用作类型签名

type Abser interface {
	Abs() float64
}
type Vertex struct {
	X, Y float64
}

func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	var a Abser
	v := Vertex{3, 4}
	a = &v // a *Vertex 实现了 Abser
	// 下面一行,v 是一个 Vertex(而不是 *Vertex)
	//v.Abs()调用时实际被转成了(&v).Abs()
	// 所以没有实现 Abser
	// 下面为错误代码
	a = v

	fmt.Println(a.Abs())
}

空接口

空接口就是没有任何方法签名的接口,它可以接收任意类型的值

func main() {
	var i interface{}
	i = 1
	i = 1.1
	i = "1"
	i = map[string]interface{}{}
	i = []int{}
	i = true
}

interface与nil

接口类似于下面这样一个结构体,一个接口变量记录了它实际指向的值和这个值的类型

type interface struct{
	data interface{}
	type Type
}

下面这个例子,给一个接口类型赋值一个bool值,实际上接口内部存储了两个值,一个是具体的值,一个是类型

var i interface{}
i = true
fmt.Printf("%v %T",i,i) // true bool

不要判断interface是否为nil

func main() {

	var i interface{}
	if i == nil {
		log.Println("is nil") 		// is nil
	}
	var ipeople *IPeople
	i = ipeople
	log.Printf("%v %T", i, i)		// nil nil
	var people *People
	i = people
	if people == nil {
		log.Println("people is nil")  // people is nil
	}
	if i == nil {
		log.Println("i is nil")
	} else {
		log.Println("i is not nil")   // i is not nil
		log.Printf("%v %T", i, i)     // nil *main.People
	}
	var people2 People

	log.Printf("%v %T", people2, people2) //{} main.People
}

type People struct {
}

type IPeople interface{}

使用断言判断接口是否为nil

语法:v,ok:=i.(type)

func main() {
	var i interface{}
	i = 1

	v, ok := i.(int)
	log.Println(v, ok) // 1 true

	var people *People
	i = people
	people, ok = i.(*People)
	log.Println(people, ok) // <nil> true

	var ipeople *IPeople
	i = ipeople
	ipeople, ok = i.(*IPeople)
	log.Println(ipeople, ok) // <nil> true

	var people1 People
	var ipeople1 IPeople
	i = people1
	people1, ok = i.(People)
	log.Println(ipeople, ok) // <nil> true
	i = ipeople1
	ipeople1, ok = i.(IPeople)
	log.Println(ipeople1, ok) // <nil> false
	if ok && ipeople==nil{
        // do...
    }
}
type People struct{}
type IPeople interface{}