【Go Time】Go语言里的空接口

什么是空接口?

空接口是特殊形式的接口类型,普通的接口都有方法,而空接口没有定义任何方法,也所以,咱们能够说全部类型都至少实现了空接口。shell

type empty_iface interface {
    
}

每个接口都包含两个属性,一个是值,一个是类型。数组

而对于空接口来讲,这二者都是nil,能够用fmt来验证一下。函数

package main
import "fmt"
func main() {
    var i interface{}
    fmt.Printf("type:T%,value:v%",i,i)
}

输出以下:code

type: <nil>,value:<nil>

如何使用空接口?

  1. 一般咱们会直接用interface{}做为类型声明一个实例,而这个实例能够承载任何类型的值。对象

    package main
    
    import "fmt"
    
    func main() {
        // 声明一个空接口实例
        var i interface{}
        
        // 存int没有问题
        i = 1
        fmt.Println(i)
        
        // 存字符串没有问题
        i = "hello"
        fmt.Println(i)
        
        // 存布尔值没有问题
        i = true
        fmt.Println(i)
    }
  2. 若是想让你的函数能够接收任意类型的值,也可使用空接口接口

    接收一个任意类型的值 示例字符串

    package main
    
    import "fmt"
    
    func myfunc(iface interface{}) {
        fmt.Println(iface)
    }
    
    func main() {
        a := 10
        b := "hello"
        c := true
        
        myfunc(a)
        myfunc(b)
        myfunc(c)
    }

    接收任意个任意类型的值 示例string

    package main
    
    import "fmt"
    
    func myfunc(ifaces ...interface{}) {
        for _,iface := range ifaces {
            fmt.Println(iface)
        }
    }
    
    func main() {
        a := 10
        b := "hellow"
        c := true
        
        myfunc(a,b,c)
    }
  3. 你也能够定义一个能够接收任意类型的array、slice、map、struct,例如这边定义一个切片it

    package main
    
    import "fmt"
    
    func main() {
        any := make([]interface{},5)
        any[0] = 11
        any[1] = "hello world"
        any[2] = []int{11,22,33}
        for _,value := range any {
            fmt.Println(value)
        }
    }

空接口几个要注意的坑

  1. 空接口能够承载任意值,但并不表明任意类型就能够承接空接口类型的值io

    从实现的角度看,任何类型的值都知足空接口。所以空接口类型能够保存任何值,也能够从空接口中取出原值。

    但要是把一个空接口类型的对象,再赋值给一个固定类型(好比int,string等类型)的对象赋值,是会报错的。

    package main
    
    func main() {
        // 声明变量a,类型int,初始值为1
        var a int = 1
        
        // 声明i变量,类型为interface,初始值为a,此时i的值变为1
        var i interface{} = a
        
        // 声明b变量,尝试赋值i
        var b int = i
    }

    Go里直接禁止了这种反向操做。报错以下:

    ./main.go:16:6: cannot use i (type interface {}) as type int in assignment: need type assertion
  2. 当空接口承载数组和切片后,该对象没法再进行切片

    package main
    
    import "fmt" 
    
    func main() {
        sli := []int{2,3,5,7,11,13}
        
        var i interface{} 
       	i = sli
        
        g := i[1:3]
        fmt.Println(g)
    }

    执行会报错

    ./main.go:16:8: cannot slice i (type interface {})
  3. 当使用空接口来接收任意类型的参数时,它的静态类型时interface{},但动态类型是(int,string仍是其余类型)咱们并不知道,所以须要使用类型断言。

    package main
    
    import "fmt" 
    
    func myfunc(i interface{}) {
        switch i.(type) {
            case int:
                fmt.Println("参数类型是 int")
            case string:
                fmt.Println("参数类型是 string")
        }
    }
    
    func main() {
        a := 10
        b := "hello"
        myfunc(a)
        myfunc(b)
    }

    输出以下

    参数类型是 int
    参数类型是 string