Go语言之类型转换规则

Type Convert in Golang

Posted by alovn on August 11, 2021

在Golang中,如果一个值v可以被显式的转换为类型T,可以使用语法(T)(v)来表示,在大多少情况下可以简化为T(v)。

一般类型

如果两个类型表示着同一个类型,则它们的值可以相互隐式转换,如类型byte和uint8、rune和int32、[]byte和[]uint8。

1
2
3
4
5
6
7
8
9
10
11
12
13
//uint8隐式转换为byte
var i uint8 = 1
var b byte = 2
b = i 
fmt.Println(i, b) //1, 1

//[]uint8隐式转换为[]byte
var s1 []uint8 = []uint8{1, 2, 3}
var s2 []byte = []byte{1}
fmt.Println(s2) //1
s2 = s1
fmt.Println(s1) //[1 2 3]
fmt.Println(s2) //[1 2 3]

假设一个非接口值x和一个非接口类型T,并假设x的类型为Tx:

  • 若类型Tx和T的底层类型相同,则x可以被显式转换为类型T。

    1
    2
    3
    4
    5
    6
    
      type T int32
      type Tx int32
      var x Tx = 1
      var t T = T(x) //显式转换
      //var t T = x //编译错误,不可隐式转换
      fmt.Println(t) //1
    
  • 如果类型Tx和T中至少有一个是非定义类型(所有的基本类型都是定义类型,一个非定义类型必为一个组合类型并且它的底层类型为它自己),并且它们的底层类型相同,则x可以被隐式转换为类型T。

    1
    2
    3
    4
    5
    
      type T []int32
      var t T
      var x = []int32{1, 2, 3} //Tx,非定义类型
      t = x //Tx类型隐式转换为了T类型
      fmt.Println(x, t) //[1 2 3] [1 2 3] 
    
  • 如果类型Tx和T的底层类型不同,但是它们都是非定义的指针类型,并且它们的基类型的底层类型相同,则x可以被显式转换为类型T。

    1
    2
    3
    4
    5
    6
    
      type Tx *int
      var t *int //非定义类型
      var a int = 1
      t = &a
      var x Tx = Tx(t) //显式转换
      fmt.Println(*x) //1
    

通道

假设一个通道值为x,它的类型Tx是一个双向通道类型,T也是一个通道类型(无论单向还是双向的)。如果Tx和T的元素类型相同并且它们中至少有一个为非定义类型,则x可以被隐式转换为类型T。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type T1 chan string
type T2 chan<- string
type T3 <-chan string

var t1 T1
var t2 T2
var t3 T3

var c chan string //非定义类型

t1 = c //隐式转换
t2 = c
t3 = c

//var _ = T2(t1) //T1不能直接转换为T2或T3
var _ = T2((chan<- string)(t1)) //T1可以间接转换为T2或T3

接口

假设一个值x和一个接口类型T,如x的类型为Tx,并且Tx实现了接口T,那么x可以被隐式转换为类型T。

动态类型为T的接口值x,可以通过类型断言的方式x.(T)安全的转换为类型T。

数值

在数值转换过程中,溢出和舍入是允许的,当一个浮点数被转换为整数时,小数部分会被舍弃(向零靠拢取整)。

1
2
var a, b = 1.6, -1.6
fmt.Println(int(a), int(b)) //1, -1

字符串

如果一个值类型为整数类型,那么这个值可以被当作rune类型显式转换为任何字符串类型。

一个字符串可以被显式转换为一个字节切片类型([]byte)或 []rune类型,反之亦然。

非类型安全指针

非类型安全指针类型是指底层类型为unsafe.Pointer的类型。

任何类型安全指针类型的值可以被显式转换为一个非类型安全指针类型,反之亦然。

任何uintptr值可以被显式转换为一个非类型安全指针类型,反之亦然。