非零基础自学Golang
文章目录
- 非零基础自学Golang
- 第12章 接口与类型
- 12.4 空接口
- 12.4.1 将值保存到空接口
- 12.4.2 从空接口取值
- 12.4.3 空接口的常见使用
第12章 接口与类型
12.4 空接口
12.4.1 将值保存到空接口
空接口(interface{})是Go语言中最特殊的接口。
在Java语言中,所有的类都继承自一个基类Object,而Go中的interface{}接口【空接口】就相当于Java语言里的Object。
在Go语言中,空接口不包含任何方法,也正因如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。
举个例子:
[ 动手写12.4.1]
package main
import "fmt"
func Log(name string, i interface{}) {
fmt.Printf("Name = %s , Type = %T , value = %v\n", name, i, i)
}
func main() {
var v1 interface{} = 1
var v2 interface{} = "abc"
var v3 interface{} = true
var v4 interface{} = &v1
var v5 interface{} = struct {
Name string
}{"Xiao Ming"}
var v6 interface{} = &v5
Log("v1", v1)
Log("v2", v2)
Log("v3", v3)
Log("v4", v4)
Log("v5", v5)
Log("v6", v6)
}
运行结果
动手写12.4.1展示了空接口可以存储数字、字符串、结构体、指针等任意类型的数值,其中v4和v6指针在不同的计算机中,数值是随机的一个地址,所以会不同。
12.4.2 从空接口取值
我们接下来看如何从空接口获取值:
[ 动手写 12.4.2]
package main
import "fmt"
func main() {
var a string = "abc"
var i interface{} = a
var b string = i
fmt.Errorf(b)
}
运行结果
动手写12.4.2运行后报错,报错结果如下:
cannot use i (type interface {}) as type string in assignment: need type assertion
这个错误的意思是不能将空接口赋值到其他类型,如果需要的话必须使用类型断言。
将动手写12.4.2改为如动手写12.4.3所示,就能成功从空接口中取值。
[ 动手写 12.4.3 ]
package main
import "fmt"
func main() {
var a string = "abc"
var i interface{} = a
var b string = i.(string)
fmt.Println(b)
}
运行结果
关于类型断言,在后面再细说
12.4.3 空接口的常见使用
我们经常使用的打印函数fmt.Println就使用了空接口,Println的定义如下:
func Println(a ...interface{}) (n int, err error)
其中interface{}前面的三个点代表的是可变长参数。
可变长参数函数即其参数数量是可变的——0个或多个。声明可变参数函数的方式是在其参数类型前带上省略符(三个点)前缀,如果除了可变长参数外还有其他参数,则可变长参数必须放置在参数列表的末尾,如fmt.Printf:
func Printf(format string, a ...interface{}) (n int, err error)
打印函数支持传入任意个值,并且值的类型也是任意的。
我们可以写一个这样的例子:
[ 动手写 12.4.4]
package main
import "fmt"
func Log(args ...interface{}) {
for num, arg := range args {
fmt.Printf("Index => %d , Value => %v \n", num, arg)
}
}
func main() {
s := make([]interface{}, 3)
s[0] = 1
s[1] = "abc"
s[2] = struct {
Num int
}{1}
// 可变长参数
fmt.Println("===== 将切片拆散 =====")
Log(s...)
fmt.Println("===== 直接传入切片 =====")
Log(s)
}
运行结果
这里可以看见,动手写12.4.4中存在这样的用法——“s…”,这个用法的意思是将切片拆散传入到参数列表中。
在本例中,Log(s…)可以等同于Log(s[0], s[1], s[2])。