Golang类型断言


系列文章:

golang实现多态

golang利用组合实现继承,和php或java面向对象的继承有何不同

Golang类型断言

golang之interface入门

interface,鸭子类型与泛型


所谓 类型断言(type assertion):

cannot convert a (type interface{}) to type string: need type assertion


直接转换


如果明确知道a的类型,可以直接转换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main() {
var i interface{}
i = "cuishuang"
f(i)
}

func f(a interface{}) string {
fmt.Println(a)

return a.(string)
}

则编译通过.


格式为 a.(对应的类型)

但如果”()”里面的类型不对,则会直接panic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main() {
var i interface{}
i = "cuishuang"
f(i)
}

func f(a interface{}) string {
fmt.Println(a.(int))

return ""
}

输出为:

1
2
3
panic: interface conversion: interface {} is string, not int

goroutine 1 [running]:




OK判别式


如上,如果类型不一致,会直接panic。所以一般在断言时,都要用OK判别式的格式(哪怕只是value, _ := a.(float32),起码这样不会panic了)

如:

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

import "fmt"

func main() {
var i interface{}
i = "cuishuang"
f(i)
}

func f(a interface{}) string {

value, _ := a.(float32)

fmt.Println("value ", value)

return ""
}

输出为:value 0


而如果:

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

import "fmt"

func main() {
var i interface{}
i = "cuishuang"
f(i)
}

func f(a interface{}) string {

value := a.(float32)

fmt.Println("value ", value)

return ""
}

则会

1
2
3
4
5
6
7
8
panic: interface conversion: interface {} is string, not float32

goroutine 1 [running]:
main.f({0x10071baa0?, 0x10072c748?})
/Users/fliter/go/src/shuang/interfacee/assert.go:13 +0xb4
main.main()
/Users/fliter/go/src/shuang/interfacee/assert.go:8 +0x2c
exit status 2

golangci-lint有一个检查项 forcetypeassert,用来强制类型断言,检查interface转换有没有进行类型校验


在断言时进行判断:

  • 如果断言失败,那么ok的值将会是false.

  • 如果断言成功, ok的值将会是true, 同时value就是所期待的正确的值

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

import "fmt"

func main() {
var i interface{}
i = "cuishuang"
f(i)
}

func f(a interface{}) string {
value,ok := a.(int)

if ok {
fmt.Println(a.(int)) //a.(int) 即 value
fmt.Println(value)
} else {
fmt.Println("i中不是int类型")
}

return ""
}

输出为:

1
i中不是int类型



配合switch语句进行判断


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import "fmt"

func main() {
var i interface{}
i = "cuishuang"
f(i)
}

func f(a interface{}) string {

switch val := a.(type) {
default:
fmt.Printf("unexpected type %T", val) // %T prints whatever type t has
break
case bool:
fmt.Printf("boolean: %t\n", val) // t has type bool
break
case int:
fmt.Printf("integer: %d\n", val) // t has type int
break
case string:
fmt.Printf("string: %s\n", val) // t has type string
break
case *bool:
fmt.Printf("pointer to boolean: %t\n", *val) // t has type *bool
break
case *int:
fmt.Printf("pointer to integer: %d\n", *val) // t has type *int

case *string:
fmt.Printf("pointer to string: %s\n", *val) // t has type *string
break

}

return ""
}

输出为:

1
string: cuishuang

参考:

深入Go语言 - 6

golang类型断言的使用(Type Assertion)