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


    什么是空接口?

    空接口是特殊形式的接口类型,普通的接口都有方法,而空接口没有定义任何方法,也因此,我们可以说所有类型都至少实现了空接口。

    type empty_iface interface {
        
    }
    

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

    而对于空接口来说,这两者都是nil,可以用fmt来验证一下。

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

    输出如下:

    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)
      }
      

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

      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,例如这边定义一个切片

      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. 空接口可以承载任意值,但并不代表任意类型就可以承接空接口类型的值

      从实现的角度看,任何类型的值都满足空接口。因此空接口类型可以保存任何值,也可以从空接口中取出原值。

      但要是把一个空接口类型的对象,再赋值给一个固定类型(比如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
      
  • 相关阅读:
    教你怎样做个有“钱”途的測试project师
    使用具体解释及源代码解析Android中的Adapter、BaseAdapter、ArrayAdapter、SimpleAdapter和SimpleCursorAdapter
    html-上左右布局方式---ShinePans
    POJ1502 MPI Maelstrom Dijkstra
    Angry IP Scanner 获取设备的IP
    【Struts2学习笔记(12)】Struts2国际化
    使用SQL Profile及SQL Tuning Advisor固定运行计划
    sage开发url替换字符串
    柯塔娜大合唱,互联网安全观
    vim水平摆放全部窗体的三个方法
  • 原文地址:https://www.cnblogs.com/mengyilingjian/p/13410690.html
Copyright © 2020-2023  润新知