前言:原因很简单,写的代码panic了。报错如下。为此专门看下golang的类型断言。
“[PANIC]interface conversion: interface {} is string, not float64”。
1、类型断言(assertion)
所谓“类型断言”即判断一个变量是不是某个类型的实例(简单来讲就是判断所属类型)。
举例例子,interface属于一般类型其具体类型是不明确的,当要将其转换成具体类型的时候就要使用类型断言。如果不使用的话一旦类型对不上就会出现类似前面所说的panic。
1.1、类型assertion和类型switch只用作用与interface{}
package mainimport ("fmt"
)func main() {var v string = "hello" // var v interface{} = "hello"s, ok := v.(string)fmt.Println("s=", s, ",ok=", ok)}
对于上述代码会得到如下错误。
1.2、断言失败则会panic
如下前者:v到string的类型assertion成功,返回s等于“hello”
如下后者:v到float64的类型assertion失败,导致panic。
package mainimport ("fmt"
)func main() {var v interface{} = "hello"s := v.(string)fmt.Println("s=", s)f := v.(float64) //会painicfmt.Println("f=", f)}
1.3、使用ok的方式避免panic
当assertion失败的时候,ok返回false就不会引发panic行为。
package mainimport ("fmt"
)func main() {var v interface{} = "hello"s, _ := v.(string)fmt.Println("s=", s)f, ok := v.(float64)if ok {fmt.Println("f=", f)} else {fmt.Println("not a float64")}}
执行结果如下:
1.4、v.(type)配合switch进行类型判断
还有一种方式就是v.(type)配合switch进行类型判断。
package mainimport ("fmt"
)func main() {//var v interface{} = "hello"var v interface{} = 1234switch t:=v.(type) {case string:fmt.Println("v is type of string")case int:fmt.Println("v is type of int")case float64:fmt.Println("v is type of float64")}}
1.5、小结
v.(T)的写法可以在运行是判断v的值是不是T类型,是的话就直接使用其值,不是则panic;
类型assertion和类型switch非常类似于C++的多态类型之间的转换。