类型转换和类型断言
Go语言的类型转换和类型断言:
- 类型转换在编译期完成,包括强制转换和隐式转换
- 类型断言在运行时确定,包括安全类型断言和非安全类型断言
Go语言要求不同类型之间必须做显式的类型转换。但似乎涉及到接口类型时,就会有所不同。
T(x),类型转换是将一个值x转换成特定类型T.
1
2
3
4
5
6
7
8
|
*Point(p) // same as *(Point(p))
(*Point)(p) // p is converted to *Point
<-chan int(c) // same as <-(chan int(c))
(<-chan int)(c) // c is converted to <-chan int
func()(x) // function signature func() x
(func())(x) // x is converted to func()
(func() int)(x) // x is converted to func() int
func() int(x) // x is converted to func() int (unambiguous)
|
x.(T),类型断言是将接口类型的值x,转换成类型T。
格式为:
1
2
3
|
x.(T)
v := x.(T)
v, ok := x.(T)
|
类型断言的必要条件是x是接口类型,非接口类型的x不能做类型断言:
1
2
|
var i int = 10
v := i.(int) //错误
|
T可以是非接口类型,如果想断言合法,则T应该实现x的接口。
T也可以是接口,则x的动态类型也应该实现接口T。
1
2
3
4
5
6
|
var x interface{} = 7 // x 的动态类型为int, 值为 7
i := x.(int) // i 的类型为 int, 值为 7
type I interface { m() }
var y I
s := y.(string) // 非法: string 没有实现接口 I (missing method m)
r := y.(io.Reader) // y如果实现了接口io.Reader和I的情况下, r的类型则为io.Reader
|
类型断言如果非法,运行时时候就会出现 impossible type assertion panic,为了避免这种情况,可以使用下面的语法:
1
2
3
|
v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
|
ok代表类型断言是否合法,如果非法ok =false,v为T的零值,这样就不会出现运行时panic了。
接口之间转换
接口之间在编译期间可以确定的情况下可以使用隐式类型转换,当然也可以用强制类型转换(不常用),所有情况下都可以使用类型断言。
1
2
3
4
5
6
7
8
9
10
|
type A interface {}
type B interface {Foo()}
// 编译时无法确定能不能转换,因此用断言
var a A
var b = a.(B)
// 编译时,可以确定
var c B
var d = A(c)
// or var d = c
// or d = c.(A)
|
接口和类型之间的转换
普通类型向接口转换,可以使用隐式类型转换
1
2
3
4
|
type A interface {}
var s = "abc"
var a A
a = s
|
接口向普通类型转换,只能使用类型断言,因为编译器无法确定
1
2
3
4
|
type A interface {}
var s string
var a A
s = a.(string)
|
type switch
switch是一个条件语句,它可以判断某个值是否匹配某个case clause。但是对于type switch,它检查的是值x的类型T是否匹配某个类型。
格式如下,类型类型断言,但是括号内的不是某个具体的类型,而是单词type:
1
2
3
|
switch x.(type) {
// cases
}
|
type switch语句中可以有一个简写的变量声明,这种情况下,等价于这个变量声明在每个case clause隐式代码块的开始位置。如果case clause只列出了一个类型,则变量的类型就是这个类型,否则就是原始值的类型。
假设下面的例子中x的类型为x interface{}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
switch i := x.(type) {
case nil:
printString("x is nil") // i的类型是 x的类型 (interface{})
case int:
printInt(i) // i的类型 int
case float64:
printFloat64(i) // i的类型是 float64
case func(int) float64:
printFunction(i) // i的类型是 func(int) float64
case bool, string:
printString("type is bool or string") // i的类型是 x (interface{})
default:
printString("don't know the type") // i的类型是 x的类型 (interface{})
}
|
type switch 不支持 fallthrought
也许你已经看到上面的例子中有一个case clause中的类型是nil,它用来匹配x为nil的interface{}的情况。