Hi,大家好,我是明哥。
在自己学习 Golang 的这段时间里,我写了详细的学习笔记放在我的个人微信公众号 《Go编程时光》,对于 Go 语言,我也算是个初学者,因此写的东西应该会比较适合刚接触的同学,如果你也是刚学习 Go 语言,不防关注一下,一起学习,一起成长。
我的在线博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime
Type Assertion
Type Assertion(中文名叫:类型断言),通过它可以做到以下几件事情
- 检查
i 是否为 nil
- 检查
i 存储的值是否为某个类型
具体的使用方式有两种:
第一种:
t := i.(T)
这个表达式可以断言一个接口对象(i)里不是 nil,并且接口对象(i)存储的值的类型是 T,如果断言成功,就会返回值给 t,如果断言失败,就会触发 panic。
来写段代码试验一下
package main
import "fmt"
func main() {
var i interface{} = 10
t1 := i.(int)
fmt.Println(t1)
fmt.Println("=====分隔线=====")
t2 := i.(string)
fmt.Println(t2)
}
运行后输出如下,可以发现在执行第二次断言的时候失败了,并且触发了 panic
10
=====分隔线=====
panic: interface conversion: interface {} is int, not string
goroutine 1 [running]:
main.main()
E:/GoPlayer/src/main.go:12 +0x10e
exit status 2
如果要断言的接口值是 nil,那我们来看看也是不是也如预期一样会触发panic
package main
func main() {
var i interface{} // nil
var _ = i.(interface{})
}
输出如下,确实是会 触发 panic
panic: interface conversion: interface is nil, not interface {}
goroutine 1 [running]:
main.main()
E:/GoPlayer/src/main.go:5 +0x34
exit status 2
第二种
t, ok:= i.(T)
和上面一样,这个表达式也是可以断言一个接口对象(i)里不是 nil,并且接口对象(i)存储的值的类型是 T,如果断言成功,就会返回其类型给 t,并且此时 ok 的值 为 true,表示断言成功。
如果接口值的类型,并不是我们所断言的 T,就会断言失败,但和第一种表达式不同的事,这个不会触发 panic,而是将 ok 的值设为 false ,表示断言失败,此时t 为 T 的零值。
稍微修改下上面的例子,如下
package main
import "fmt"
func main() {
var i interface{} = 10
t1, ok := i.(int)
fmt.Printf("%d-%t\n", t1, ok)
fmt.Println("=====分隔线1=====")
t2, ok := i.(string)
fmt.Printf("%s-%t\n", t2, ok)
fmt.Println("=====分隔线2=====")
var k interface{} // nil
t3, ok := k.(interface{})
fmt.Println(t3, "-", ok)
fmt.Println("=====分隔线3=====")
k = 10
t4, ok := k.(interface{})
fmt.Printf("%d-%t\n", t4, ok)
t5, ok := k.(int)
fmt.Printf("%d-%t\n", t5, ok)
}
运行后输出如下,可以发现在执行第二次断言的时候,虽然失败了,但并没有触发了 panic。
10-true
=====分隔线1=====
-false
=====分隔线2=====
<nil> - false
=====分隔线3=====
10-true
10-true
上面这段输出,你要注意的是第二个断言的输出在-false 之前并不是有没有输出任何 t2 的值,而是由于断言失败,所以 t2 得到的是 string 的零值也是 "" ,它是零长度的,所以你看不到其输出。
Type Switch
如果需要区分多种类型,可以使用 type switch 断言,这个将会比一个一个进行类型断言更简单、直接、高效。
package main
import "fmt"
func findType(i interface{}) {
switch x := i.(type) {
case int:
fmt.Println(x, "is int")
case string:
fmt.Println(x, "is string")
case nil:
fmt.Println(x, "is nil")
default:
fmt.Println(x, "not type matched")
}
}
func main() {
findType(10) // int
findType("hello") // string
var k interface{} // nil
findType(k)
findType(10.23) //float64
}
输出如下
10 is int
hello is string
<nil> is nil
10.23 not type matched
额外说明一下:
- 如果你的值是 nil,那么匹配的是
case nil
- 如果你的值在 switch-case 里并没有匹配对应的类型,那么走的是 default 分支
参考文章
系列导读
01. 开发环境的搭建(Goland & VS Code)
02. 学习五种变量创建的方法
03. 详解数据类型:****整形与浮点型
04. 详解数据类型:byte、rune与string
05. 详解数据类型:数组与切片
06. 详解数据类型:字典与布尔类型
07. 详解数据类型:指针
08. 面向对象编程:结构体与继承
09. 一篇文章理解 Go 里的函数
10. Go语言流程控制:if-else 条件语句
11. Go语言流程控制:switch-case 选择语句
12. Go语言流程控制:for 循环语句
13. Go语言流程控制:goto 无条件跳转
14. Go语言流程控制:defer 延迟调用
15. 面向对象编程:接口与多态
16. 关键字:make 和 new 的区别?
17. 一篇文章理解 Go 里的语句块与作用域
18. 学习 Go 协程:goroutine
19. 学习 Go 协程:详解信道/通道
20. 几个信道死锁经典错误案例详解
21. 学习 Go 协程:WaitGroup
22. 学习 Go 协程:互斥锁和读写锁
23. Go 里的异常处理:panic 和 recover
24. 超详细解读 Go Modules 前世今生及入门使用
25. Go 语言中关于包导入必学的 8 个知识点
26. 如何开源自己写的模块给别人用?
27. 说说 Go 语言中的类型断言?
28. 这五点带你理解Go语言的select用法
|
请发表评论