1、介绍
Golang 语言是一门静态类型的编程语言,我们在编写代码时,为了提升代码的灵活性,有时会使用空接口类型,对于空接口类型的变量,一般会通过类型断言判断变量的类型,而且可能还会遇到遇到类型转换的场景,下面我们对类型的断言、类型转换和类型选择。
2、编程技巧
类型断言,类型端要提供了访问接口类型值的底层具体值的方式,这是需要注意的是被类型断言的值必须是接口类型的值,类型断言返回两个值,被断言的接口类型值的底层具体值和一个表示是否断言成功的布尔类型的值。
t,ok := i.(T)
未使用类型断言:
func main() {
id := getVal(1)
fmt.Println(id)
}
func getVal(val interface{}) interface{} {
return val
}
使用类型断言:
func main() {
id := getVal(1)
id, ok := id.(int);
if !ok {
err := errors.New("illegal paramter")
fmt.Println(err)
return
}
fmt.Println(id)
}
func getVal(val interface{}) interface{} {
return val
}
阅读上面这两段代码,main 函数中都是通过调用getVal()函数,使用类型推断的方式给变量id 赋值,不同的是main 函数,第一段代码中未使用类型断言,第二段代码中使用了类型断言,所以第一代码的main 函数如果调用 getVa()函数时传递非整型参数,也可以正常输出;第二段代码的main 函数如果调用 getVal() 函数时传递非整型参数,将会被断言代码拦截。
类型转换:
类型转换的表达式T(v),将v 转换为类型T 。关于类型转换,我们需要注意的“坑”如下所示:
整型之间的转换:
func main() {
var a int
a = 128
b := int8(a)
fmt.Println(b)
}
输出结果:-128
阅读上面这段代码, int 类型的变量 a 赋值为128 ,将变量a 转换为int8 类型的变量b , 输出变量b 的结果是 -128 ,原因是int 类型和 int8 类型的取值范围不同。
浮点型转为整形:
import "fmt"
func main() {
var a float64
a = 3.1415926
b := int(a)
fmt.Println(b)
}
输出结果:3
浮点型float64的变量a, 转换为int 类型的变量b ,输出结果是3,变量a 值的小数部分被截掉了。
整型转换为字符串类型:
import "fmt"
func main() {
var a int
a = -1
b := string(a)
fmt.Println(b)
}
输出结果:�
int 类型变量 a,转换为 string 类型变量 b,变量 b 的输出结果是 �
,表示未知字符,原因是 Unicode 码点(code point)中没有 -1。
字符串类型和切片(字节切片和字符切片)类型相互转换:
import "fmt"
func main() {
var a string
a = "编程"
b := []byte(a)
fmt.Println(b)
c := []rune(a)
fmt.Println(c)
}
输出结果:
[231 188 150 231 168 139]
[32534 31243]
将字符串类型的变量a 分别转换为字节切片类型变量b 和字符切片类型变量c,它们的输出结果不同,原因是UTF-8 编码一个中文汉字是3个字节,3个字节代表1个字符 。而字符切片类型的元素本身就是Unicode 字符。
类型选择:
func main() {
var a interface{}
a = false
switch val := a.(type) {
case int:
fmt.Printf("val:%d type:%T\n", val, val)
case string:
fmt.Printf("val:%d type:%T\n", val, val)
default:
fmt.Printf("unknowtype:%T\n", val)
}
}
这段代码使用的 type swtich 判断空接口类型变量a 的实际数据类型是否为我们预定义的类型之一。