一 类型转换

与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 数字类型之间的转换

以下规则适用于非常量数值之间的转换:

  1. 在整型之间进行转换时,如果值为有符号整数,则将其符号扩展为隐式无限精度;否则扩展精度为0。然后将其截断以适合结果类型的大小。例如,如果v := uint16(0x10F0),那么uint32(int8(v)) == 0xFFFFFFF0。转换始终产生有效的值,没有溢出的迹象。
  2. 将浮点数转换为整型时,小数部分将被舍弃掉(向零取整)。
  3. 将整型或浮点数转换为浮点类型时,或将复数转换为另一种复数类型时,结果值将舍入为目标类型指定的精度。例如,float32类型的变量x的值可能使用超出IEEE-754 32位数字的附加精度来存储,但float32(x)表示将x的值舍入为32位精度的结果。同理,x + 0.1可能使用超过32位的精度,但float32(x + 0.1)则不会。

1.2 转为字符串或从字符串转换

  1. 将有符号整型或无符号整型转换为字符串类型会生成包含整型的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"
  2. 将字节切片转换成字符串类型会生成一个字符串,其连续字节是切片的元素。

    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ø"
  3. 将符文切片转换为字符串类型会生成一个字符串,该字符串是符文各个字符的串联。

    string([]rune{0x767d, 0x9d6c, 0x7fd4})   // "\u767d\u9d6c\u7fd4" == "白鵬翔"
    string([]rune{})                         // ""
    string([]rune(nil))                      // ""
    
    type MyRunes []rune
    string(MyRunes{0x767d, 0x9d6c, 0x7fd4})  // "\u767d\u9d6c\u7fd4" == "白鵬翔"
  4. 将字符串转换为字节切片类型会生成一个切片,其连续元素是字符串的各个字节

    []byte("hellø")   // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
    []byte("")        // []byte{}
    
    MyBytes("hellø")  // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
  5. 将字符串转换为符文切片类型会生成包含字符串各个Unicode码点的切片

    []rune(MyString("白鵬翔"))  // []rune{0x767d, 0x9d6c, 0x7fd4}
    []rune("")                 // []rune{}
    
    MyRunes("白鵬翔")           // []rune{0x767d, 0x9d6c, 0x7fd4}

二 类型推导

类型推导,或者说隐式类型转换,就是在声明一个变量而不指定其类型时(即使用不带类型的:=语法或var =表达式语法),变量的类型由右值推导得出。

当右值声明了类型时,新变量的类型与其相同:

var i int
j := i // j 也是一个 int

不过当右边包含未指明类型的数值常量时,新变量的类型就可能是intfloat64complex128了,这取决于常量的精度:

i := 42           // int
f := 3.142        // float64
g := 0.867 + 0.5i // complex128

参考:
https://golang.org/ref/spec#Conversions

文章目录