【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
相關文章
相關標籤/搜索