首页 > 编程笔记 > Go语言笔记 阅读:5

Go语言空接口用法汇总(附带实例)

Go语言中的空接口类型是指在接口中没有任何函数,用“interface{}”表示。

因为在空接口中没有任何函数,所以任何类型的变量都可以实现空接口。也正因为如此,在实际开发过程中,开发者既可以使用空接口保存任何类型的值,又可以从空接口中获取任何类型的值。

使用空接口保存值

空接口变量在没有被赋值的情况下,它的值及其数据类型都是 nil。对空接口变量执行赋值操作,空接口变量的值及其数据类型将发生变化。

【实例 1】使用空接口保存基础类型变量的值。
声明空接口后,在 main() 函数中声明空接口变量,格式化输出空接口变量的值及其类型。分别声明初始值为 711 的 int 类型变量、初始值为“hello, go”的 string 类型变量,以及初始值为 true 的 bool 类型变量,把这 3 个变量的值依次赋值给空接口变量,并格式化输出此时空接口变量的值及其类型。代码如下:
package main //声明 main 包

import "fmt" //导入 fmt 包,用于打印字符串

type noFunctions interface{} //声明空接口

func main() { //声明 main()函数
    var nf noFunctions //声明空接口变量
    fmt.Printf("空接口保存的值:%v,空接口的类型:%T\n", nf, nf) //打印空接口变量的值及其类型
    num := 711 //声明初始值为 711 的 int 类型变量 num
    nf = num //把变量 num 的值赋值给空接口变量 nf
    fmt.Printf("空接口保存的值:%v,空接口的类型:%T\n", nf, nf) //打印空接口变量的值及其类型
    str := "hello, go" //声明初始值为"hello, go"的 string 类型变量 str
    nf = str //把变量 str 的值赋给空接口变量 nf
    fmt.Printf("空接口保存的值:%v,空接口的类型:%T\n", nf, nf) //打印空接口变量的值及其类型
    b := true //声明初始值为 true 的 bool 类型变量 b
    nf = b //把变量 b 的值赋值给空接口变量 nf
    fmt.Printf("空接口保存的值:%v,空接口的类型:%T\n", nf, nf) //打印空接口变量的值及其类型
}
运行结果如下:

空接口保存的值:<nil>,空接口的类型:<nil>
空接口保存的值:711,空接口的类型:int
空接口保存的值:hello, go,空接口的类型:string
空接口保存的值:true,空接口的类型:bool


空接口不仅可以保存基础变量的值,还能保存切片类型的数据、映射类型的数据和结构体中字段类型的数据。具体的使用方式如下:
下例演示如何保存切片类型的数据、映射类型的数据和结构体中字段类型的数据。

【实例 2】空接口类型的切片、映射和结构体中的字段。
初始化空接口类型的切片,切片中的数据为 123、hello 和 true;初始化空接口类型的映射,映射的值为“map[price:15 product:cap]”;声明表示汽车的结构体,其中包含一个表示价格的空接口类型字段,依次把 159800 和“壹拾伍万玖仟捌佰圆整”赋值给这个字段。代码如下:
package main //声明 main 包

import "fmt" //导入 fmt 包,用于打印字符串

func main() { //声明 main()函数
    s := []interface{}{123, "hello", true} //初始化空接口类型的切片
    fmt.Printf("切片中的数据:%v\n", s) //打印切片中的数据
    m := map[string]interface{}{} //初始化空接口类型的映射
    m["product"] = "cap" //初始化一组键值对,与键对应的值的类型是 string
    m["price"] = 15 //初始化一组键值对,与键对应的值的类型是 int
    fmt.Printf("集合中的数据:%v\n", m) //打印映射中的数据
    var car struct { //声明一个表示汽车的结构体
        price interface{} //声明表示价格的空接口类型字段
    }
    car.price = 159800 //初始化字段的值,其类型是 int
    //打印结构体中的字段数据及其数据类型
    fmt.Printf("结构体中的字段数据:%v,其数据类型:%T\n", car.price, car.price)
    car.price = "壹拾伍万玖仟捌佰圆整" //对字段重新赋值,其类型是 string
    //打印结构体中的字段数据及其数据类型
    fmt.Printf("结构体中的字段数据:%v,其数据类型:%T\n", car.price, car.price)
}
运行结果如下:

切片中的数据:[123 hello true]
集合中的数据:map[price:15 product:cap]
结构体中的字段数据:159800,其数据类型:int
结构体中的字段数据:壹拾伍万玖仟捌佰圆整,其数据类型:string

从空接口中获取值

空接口变量被赋值后,如果直接从中获取这个值,并把它赋值给与其具有相同数据类型的另一个变量,将发生编译错误。

初始化一个值为 711 的 int 类型变量 num,再初始化一个空接口变量,把变量 num 的值赋给这个空接口变量,接着直接从空接口中获取值,并将其赋给 int 类型变量 value,打印 int 类型变量 value 的值。代码如下:
package main //声明 main 包

import "fmt" //导入 fmt 包,用于打印字符串

func main() { //声明 main()函数
    num := 711 //初始化值为 711 的 int 类型变量 num
    var nf interface{} = num //初始化空接口变量,把变量 num 的值赋给这个空接口变量
    var value int = nf //直接从空接口中获取值,并将其赋给 int 类型变量 value
   fmt.Printf("value = %v\n", value) //打印 int 类型变量 value 的值
}
上述代码编写时,会出现编译错误。把鼠标光标移至第 8 行代码的方框处,编译器弹出如下图所示的报错信息。


把变量 num 的值赋给空接口变量 nf 后,虽然空接口变量 nf 的值是 int 类型,但是变量 nf 的数据类型仍然是空接口类型,这就是出现编译错误的原因。

下面使用“类型断言”修改第8行代码,代码如下:
var value int = nf.(int)

比较空接口保存的值

使用空接口保存不同的值后,可以使用“==”运算符比较。在比较空接口保存的值时,需要注意以下几个问题。

1) 当空接口类型是基础类型、数组类型或结构体类型时,不论空接口的类型是否相同,都可以比较空接口保存的值。

先声明一个空接口变量 num,设置它的初始值为 11,再声明一个空接口变量 str,设置它的初始值为“hello”,接着分别打印这两个空接口变量的值及其数据类型,使用“==”运算符比较这两个空接口变量的值。代码如下:
package main //声明 main 包

import "fmt" //导入 fmt 包,用于打印字符串

func main() { //声明 main()函数
    var num interface{} = 11 //声明空接口变量 num,设置初始值为 11
    //打印变量 num 的值及其数据类型
    fmt.Printf("空接口变量 num 的值:%v,其数据类型:%T\n", num, num)
    var str interface{} = "hello" //声明空接口变量 str,设置初始值为 hello
    //打印变量 str 的值及其数据类型
    fmt.Printf("空接口变量 str 的值:%v,其数据类型:%T\n", str, str)
    fmt.Println("num 和 str 的比较结果:", num == str) //打印对空接口保存的值进行比较后的结果
}
运行结果为:

空接口变量 num 的值:11,其数据类型:int
空接口变量 str 的值:hello,其数据类型:string
num 和 str 的比较结果:false


2) 如果空接口类型是切片类型或映射类型,则无法比较空接口保存的值。

声明空接口变量 sl_1,设置它的初始值为包含 5 个元素的 int 类型切片,再声明一个空接口变量 sl_2,设置它的初始值为包含 10 个元素的 int 类型切片,使用“==”运算符比较这两个空接口变量的值。代码如下:
package main //声明 main 包

import "fmt" //导入 fmt 包,用于打印字符串

func main() { //声明 main()函数
    //声明空接口变量 sl_1,设置初始值为包含 5 个元素的 int 类型切片
    var sl_1 interface{} = []int{5}
    //声明空接口变量 sl_2,设置初始值为包含 10 个元素的 int 类型切片
    var sl_2 interface{} = []int{10}
    fmt.Println("sl_1 == sl_2") //打印比较空接口保存的值之后的结果
}
运行结果为:

panic: runtime error: comparing uncomparable type []int

运行结果是运行时错误,提示 int 类型的切片(即“[]int”)是不可比较的类型。

相关文章