类型断言(Type Assertion)
非安全的类型断言
package main
import "fmt"
func main() {
var a interface{} = "ss"
t := a.(string)
fmt.Printf("%v", t)
}
在上面,我们将一个类型为 interface{}
的变量转换成了 string 类型。
我们可以使用类型断言(type assertion),以将一个类型为 interface{}
的变量,转换为基本数据类型或者复杂数据类型。
所谓”非安全“的类型断言,是指如果这个转换失败,则会直接在运行时报错:
package main
import "fmt"
func main() {
var a interface{} ="ss"
t:= a.(int)
fmt.Printf("%d",t)
}
Error:
panic: interface conversion: interface {} is string, not int
goroutine 1 [running]:
main.main()
/Working/GoPlayGround/main.go:7 +0x45
因此,就有了安全的类型断言。
安全的类型断言
package main
import "fmt"
func main() {
var s interface{} = "BrainWu"
if v, ok := s.(string); ok { // invalid type assertion: s.(string) (non-interface type string on left)
fmt.Println(v)
}
}
我们可以使用类型断言,将一个类型为 interface{}
的变量,转换为基本数据类型或者复杂数据类型:
package main
import "fmt"
func main() {
var a interface{} = 10
t, ok := a.(int)
if ok {
fmt.Println("int", t)
}
t2, ok := a.(float32)
if ok {
fmt.Println("float32", t2)
}
}
在进行安全的类型断言时,可以使用两个参数来接收返回值,其中第一个参数是转换成功后的值,一个是 bool,用于指示这次类型转换是否成功(如果转换失败,则 v
为期待转换类型的默认值),比如:
package main
import "fmt"
func main() {
var s interface{} = "test"
v1, ok := s.(int)
if ok { // invalid type assertion: s.(string) (non-interface type string on left)
fmt.Println(v1)
}
fmt.Println(v1)
var s2 interface{} = 11
v2, ok := s2.(AAA)
if ok {
fmt.Println(v2)
}
fmt.Println(v2)
}
type AAA struct {
bb int
}
// output
0
{0}
强制类型转换
golang的类型转换和C/C++、Java等语言的类型转换还有点区别
- C/C++等语言有隐式类型转换,Golang中没有
- Golang中的类型转换分强制类型转换和类型断言
在C/C++中:
int main()
{
int a=5;
float b=3.5;
printf("%f",a*b);
}
这样的代码是没有问题的,编译器隐式的把a向上转为float类型。 但是在golang中,
package main
import "fmt"
func main() {
var a float32 = 5.6
var b int = 10
fmt.Println (a * b)
}
这样的代码会报错,因为类型不匹配,这时候就需要强制类型转换:
package main
import "fmt"
func main() {
var a float32 = 5.6
var b int = 10
fmt.Println (a * float32(b))
}
这样就不会报错了,普通变量类型int、float、string 都可以使用 type (a)
这种形式来进行强制类型转换,,比如
var a int32 = 10
var b int64 = int64(a)
var c float32 = 12.3
var d float64 =float64(c)
String 与数值类型之间的转换
package main
import "strconv"
func main() {
// string到int
int, err := strconv.Atoi(string)
// string到int64
int64, err := strconv.ParseInt(string, 10, 64)
// int到string
string := strconv.Itoa(int)
// int64到string
string := strconv.FormatInt(int64, 10)
}
int32 枚举与数值类型之间的转换
package main
import "fmt"
type ConstantPromotionrulestatus int32
const (
Constant_PROMOTION_RULE_STATUS_DISABLED ConstantPromotionrulestatus = 0
Constant_PROMOTION_RULE_STATUS_DELETED ConstantPromotionrulestatus = 1
)
func main() {
var a int32 = int32(Constant_PROMOTION_RULE_STATUS_DISABLED)
fmt.Println(a)
var b int32 = 1
var c ConstantPromotionrulestatus = ConstantPromotionrulestatus(b)
fmt.Print(c)
}
指针的强制类型转换
golang中指针也是有类型的:
package main
func main() {
var a int = 10
var p *int = &a
var c *int64
c = (*int64)(p)
}
但是,上面代码会报编译错误,编译器会提示cannot convert p (type \*int) to type \*int64
。因为,指针的强制类型转换需要用到unsafe包中的函数实现:
package main
import "unsafe"
import "fmt"
func main() {
var a int = 10
var b *int = &a
var c *int64 = (*int64)(unsafe.Pointer(b))
fmt.Println(*c)
}
Reference
- https://golang.org/pkg/strconv/
- https://blog.csdn.net/bobodem/article/details/80182096
- https://stackoverflow.com/questions/18041334/convert-interface-to-int/18041561
- https://studygolang.com/articles/21591