[toc]

类型转换

Go 语言提供了一种在不同但相互兼容的类型之间相互转换的方式,这种转换非常有用并且是安全的。但是需要注意的是在数值之间进行转换可能造成其他问题,如精度丢失或者错误的结果。以下是类型转换的语法:

  • resultOfType := Type(expression)

几个例子:

1
2
3
4
x := int16(2345)        // 声明一个类型为int16的整数,其值为2345
y := int32(x) // 将int16类型的整数转换为int32类型
a := uint16(65000) // 声明一个类型为uint16类型的整数
b := int16(a) // 转换为int16类型,虽然能转换成功,但是由于65000超过in16类型的范围,会导致结果错误,b的值为 -536

另外在 Go 语言中可以通过 type 关键字声明类型,如 type StringsSlice []string[]stringstring 类型的切片)声明为 StringSlice 类型。

类型断言

说到类型断言就需要先了解下 Go 语言中的接口。在 Go 语言中接口是一个自定义类型。它声明了一个或者多个方法。任何实现了这些方法的对象(类型)都满足这个接口。

接口是完全抽象的,不能实例化。interface{} 类型表示一个空接口,任何类型都满足空接口。也就是说 interface{} 类型的值可以用于表示任意 Go 语言类型的值。

这里的空接口有点类似于 Python 语言中的 object 实例。既然 interface{} 可以用于表示任意类型,那有的时候我们需要将 interface{} 类型转换为我们需要的类型,这个操作称为类型断言。

一般情况下只有我们希望表达式是某种特定类型的值时才使用类型断言。Go 语言中可以使用以下语法:

  • resultOfType, boolean := expression.(Type):安全的类型断言。
  • resultOfType := expression.(Type):非安全的类型断言,失败时程序会产生异常。

创建源文件 type_t.go,输入以下源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"fmt"
)

func main() {
x := uint16(65000)
y := int16(x) // 将 x转换为int16类型
fmt.Printf("type and value of x is: %T and %d\n", x, x) // %T 格式化指令的作用是输出变量的类型
fmt.Printf("type and value of y is: %T and %d\n", y, y)

var i interface{} = 99 // 创建一个interface{}类型,其值为99
var s interface{} = []string{"left", "right"}
j := i.(int) // 我们假设i是兼容int类型,并使用类型断言将其转换为int类型
fmt.Printf("type and value of j is: %T and %d\n", j, j)

if s, ok := s.([]string); ok { // 创建了影子变量,if的作用域中覆盖了外部的变量s
fmt.Printf("%T -> %q\n", s, s)
}
}

运行程序:

1
2
3
4
5
$ go run type_t.go
type and value of x is: uint16 and 65000
type and value of y is: int16 and -536
type and value of j is: int and 99
[]string -> ["left" "right"]