本文最初发表在我的个人博客,查看原文,获得更好的阅读体验
一 类型转换
与C不同的是,Go在不同类型的项之间赋值时需要显式转换。显示转换语法形如T(x)
,其中T
为要转换的目标类型,x
是一个可以转换为T
的表达式。
例如:
一些关于数值的转换:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
或者,更加简单的形式:
i := 42
f := float64(i)
u := uint(f)
如果类型以*
或<-
开头,或者以关键字func
开头却没有结果列表,则为了避免歧义,必要时必须将其用括号括起来:
*Point(p) // 同 *(Point(p))
(*Point)(p) // p 被转换为 *Point
<-chan int(c) // 同 <-(chan int(c))
(<-chan int)(c) // c 被转换为 <-chan int
func()(x) // 函数签名 func() x
(func())(x) // x 被转换为 func()
(func() int)(x) // x 被转换为 func() int
func() int(x) // x 被转换为 func() int (明确的)
特定的规则适用于数字类型之间或与字符串类型之间的(非常量)转换。这些转换可能会更改x
的表示形式,并且产生运行时开销。所有其他转换只改变类型,不会改变x
的表示形式。
没有语言机制在指针和整数之间进行转换,
unsafe
包在受限情况下实现了该功能。
1.1 数字类型之间的转换
以下规则适用于非常量数值之间的转换:
- 在整型之间进行转换时,如果值为有符号整数,则将其符号扩展为隐式无限精度;否则扩展精度为0。然后将其截断以适合结果类型的大小。例如,如果
v := uint16(0x10F0)
,那么uint32(int8(v)) == 0xFFFFFFF0
。转换始终产生有效的值,没有溢出的迹象。 - 将浮点数转换为整型时,小数部分将被舍弃掉(向零取整)。
- 将整型或浮点数转换为浮点类型时,或将复数转换为另一种复数类型时,结果值将舍入为目标类型指定的精度。例如,
float32
类型的变量x
的值可能使用超出IEEE-754 32位数字的附加精度来存储,但float32(x)
表示将x
的值舍入为32位精度的结果。同理,x + 0.1
可能使用超过32位的精度,但float32(x + 0.1)
则不会。
1.2 转为字符串或从字符串转换
-
将有符号整型或无符号整型转换为字符串类型会生成包含整型的UTF-8表示形式的字符串。超出有效Unicode码点范围的值将被转成
"\uFFFD"
。string('a') // "a" string(-1) // "\ufffd" == "\xef\xbf\xbd" string(0xf8) // "\u00f8" == "ø" == "\xc3\xb8" type MyString string MyString(0x65e5) // "\u65e5" == "日" == "\xe6\x97\xa5"
-
将字节切片转换成字符串类型会生成一个字符串,其连续字节是切片的元素。
string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}) // "hellø" string([]byte{}) // "" string([]byte(nil)) // "" type MyBytes []byte string(MyBytes{'h', 'e', 'l', 'l', '\xc3', '\xb8'}) // "hellø"
-
将符文切片转换为字符串类型会生成一个字符串,该字符串是符文各个字符的串联。
string([]rune{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔" string([]rune{}) // "" string([]rune(nil)) // "" type MyRunes []rune string(MyRunes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔"
-
将字符串转换为字节切片类型会生成一个切片,其连续元素是字符串的各个字节
[]byte("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'} []byte("") // []byte{} MyBytes("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
-
将字符串转换为符文切片类型会生成包含字符串各个Unicode码点的切片
[]rune(MyString("白鵬翔")) // []rune{0x767d, 0x9d6c, 0x7fd4} []rune("") // []rune{} MyRunes("白鵬翔") // []rune{0x767d, 0x9d6c, 0x7fd4}
二 类型推导
类型推导,或者说隐式类型转换,就是在声明一个变量而不指定其类型时(即使用不带类型的:=
语法或var =
表达式语法),变量的类型由右值推导得出。
当右值声明了类型时,新变量的类型与其相同:
var i int
j := i // j 也是一个 int
不过当右边包含未指明类型的数值常量时,新变量的类型就可能是int
,float64
或 complex128
了,这取决于常量的精度:
i := 42 // int
f := 3.142 // float64
g := 0.867 + 0.5i // complex128