Golang 类型转换的实现(断言、强制、显式类型)
作者:动态一时爽,重构火葬场
将一个值从一种类型转换到另一种类型,便发生了类型转换,在go可以分为断言、强制、显式类型转换,本文就详细的介绍一下这就几种转换方式,具有一定的参考价值,感兴趣的可以了解一下
将一个值从一种类型转换到另一种类型,便发生了类型转换。静态语言如c/c++,Java提供了隐性的类型转换,但对于golang这种强类型系统则不一样,golang并不支持自动类型转换或者隐性类型转换。
在go可以分为断言、强制、显式类型转换。
通常说的类型转换是指断言,强制一般不会用到,显式是基本的类型转换
断言
断言通过判断接口x是否不是nil且为T类型
var s = x.(T)
具体而言,在T不为接口时,要求x的动态类型就是T,并且T必须实现了x接口;否则类型断言无效,因为x不可能储存类型T的值
动态类型:接口类型可以包含对实现接口的任何类型的实例的引用(接口具有所谓的动态类型)
type I interface{ F() } type S struct{} func (S) F() { } type T struct{} func (T) F() { } // 此时静态类型为接口I var x I // 此时动态类型为结构体S x = S{} // 重赋予x动态类型为结构体T x = T{}
在T为接口时,x必须实现接口T
断言失败会触发panic,当然也可以s,ok:=x.(T)
,使用ok表示是否成功。
// 接口x转换为非接口类型 var x interface{} = 1 y:=x.(int) // 接口x转换为接口类型 type TypeAssertA interface { typeAssertA() } type TypeAssertB interface { typeAssertB() } type ta struct {} func (t ta) typeAssertA() {} func (t ta) typeAssertB() {} // ta结构既实现了TypeAssertA又实现TypeAssertB,因此可以在两种接口类型之间相互转换 var x TypeAssertA = ta{} y:=x.(TypeAssertB)
switch断言
switch判断具体值类型,而在case中匹配具体类型。也可以i:=x.(type)
直接得到匹配类型的值
强制
通过unsafe等进行强制类型转换
比如将floag64类型转换为uint64类型,可能值表现不同,但内存二进制储存却是一样的
var f float64 u:= *(*uint64)(unsafe.Pointer(&f))
还可以用来进行接口类型检测
// 检查contextImpl是否实现了context接口 var c Context=(*ContextImpl)(nil)
显式
将一个类型表达式转换为另一个
var s =T(x)
在碰到*
,<-
或者func
开头的,最好使用括号以防止误用
*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
- 忽略struct标签,x类型与T具有相同的基础类型
- 忽略 struct 标记 x 的类型和 T 是未定义类型的指针类型,并且它们的指针基类型具有相同的基础类型。
- x 的类型和 T 都是整数或浮点类型。
- x 的类型和 T 都是复数类型。
- x 的类型是整数或 [] byte 或 [] rune,并且 T 是字符串类型。
或者x 的类型是字符串,T 类型是 [] byte 或 [] rune。
注意可以赋值为指的是(V为x类型):
- V等于T
- V和T是具有相同元素类型的通道类型,V是双向channel,且V或T中至少有一个不是以type命名的类型。
- T是接口类型,但不是类型参数,x实现了T。
- x是预先声明的标识符nil, T是指针、函数、切片、映射、通道或接口类型,但不是类型参数。
- x是一个没有类型的常量,可以用类型T的值表示。
此外,如果x的类型V或T是类型参数,则在下列条件之一适用时,x可赋值给类型T的变量:
- x是预先声明的标识符nil, T是一个类型参数,x可以赋值给T的类型集中的每个类型。
- V不是一个命名类型,T是一个类型参数,x可以赋值给T的类型集中的每个类型。
- V是一个类型参数,T不是一个命名类型,V的类型集中的每个类型的值都可以赋值给T。
Ref
- https://learnku.com/articles/42797
- https://golang.google.cn/ref/spec#Type_assertions
- https://www.digitalocean.com/community/tutorials/how-to-convert-data-types-in-go
- https://golang.org/ref/spec#Conversions
- https://stackoverflow.com/questions/33337403/what-does-dynamic-type-mean-in-a-go-interface
- https://go.dev/ref/spec#Assignability
到此这篇关于Golang 类型转换的实现(断言、强制、显式类型)的文章就介绍到这了,更多相关Golang 类型转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!