golang: 类型转换和类型断言
类型转换在程序设计中都是不可避免的问题。当然有一些语言将这个过程给模糊了,大多数时候开发者并不需要去关注这方面的问题。但是golang中的类型匹配是很严格的,不同的类型之间通常需要手动转换,编译器不会代你去做这个事。我之所以说通常需要手动转换,是因为interface类型作为一个特例,会有不同的处理方式。 golang中的所有类型都有自己的默认值,对此我做了个测试。 $GOPATH/src —-typeassert_test ——–main.go main.go的代码如下: package main import ( "fmt" ) type myStruct struct { name bool userid int64 } var structZero myStruct var intZero int var int32Zero int32 var int64Zero int64 var uintZero uint var uint8Zero uint8 var uint32Zero uint32 var uint64Zero uint64 var byteZero byte var boolZero bool var float32Zero float32 var float64Zero float64 var stringZero string var funcZero func(int) int var byteArrayZero [5]byte var boolArrayZero [5]bool var byteSliceZero []byte var boolSliceZero []bool var mapZero map[string]bool var interfaceZero interface{} var chanZero chan int var pointerZero *int func main() { fmt.Println("structZero: ",structZero) fmt.Println("intZero: ",intZero) fmt.Println("int32Zero: ",int32Zero) fmt.Println("int64Zero: ",int64Zero) fmt.Println("uintZero: ",uintZero) fmt.Println("uint8Zero: ",uint8Zero) fmt.Println("uint32Zero: ",uint32Zero) fmt.Println("uint64Zero: ",uint64Zero) fmt.Println("byteZero: ",byteZero) fmt.Println("boolZero: ",boolZero) fmt.Println("float32Zero: ",float32Zero) fmt.Println("float64Zero: ",float64Zero) fmt.Println("stringZero: ",stringZero) fmt.Println("funcZero: ",funcZero) fmt.Println("funcZero == nil?",funcZero == nil) fmt.Println("byteArrayZero: ",byteArrayZero) fmt.Println("boolArrayZero: ",boolArrayZero) fmt.Println("byteSliceZero: ",byteSliceZero) fmt.Println("byteSliceZero's len?",len(byteSliceZero)) fmt.Println("byteSliceZero's cap?",cap(byteSliceZero)) fmt.Println("byteSliceZero == nil?",byteSliceZero == nil) fmt.Println("boolSliceZero: ",boolSliceZero) fmt.Println("mapZero: ",mapZero) fmt.Println("mapZero's len?",len(mapZero)) fmt.Println("mapZero == nil?",mapZero == nil) fmt.Println("interfaceZero: ",interfaceZero) fmt.Println("interfaceZero == nil?",interfaceZero == nil) fmt.Println("chanZero: ",chanZero) fmt.Println("chanZero == nil?",chanZero == nil) fmt.Println("pointerZero: ",pointerZero) fmt.Println("pointerZero == nil?",pointerZero == nil) } $ cd $GOPATH/src/typeassert_test $ go build $ ./typeassert_test 您可以清楚的了解到各种类型的默认值。如bool的默认值是false,string的默认值是空串,byte的默认值是0,数组的默认就是这个数组成员类型的默认值所组成的数组等等。然而您或许会发现在上面的例子中:map、interface、pointer、slice、func、chan的默认值和nil是相等的。关于nil可以和什么样的类型做相等比较,您只需要知道nil可以赋值给哪些类型变量,那么就可以和哪些类型变量做相等比较。官方对此有明确的说明:http://pkg.golang.org/pkg/builtin/#Type,也可以看我的另一篇文章:[golang:详解interface和nil](http://my.oschina.net/goal/blog/194233)。所以现在您应该知道nil只能赋值给指针、channel、func、interface、map或slice类型的变量。如果您用int类型的变量跟nil做相等比较,panic会找上您。 对于字面量的值,编译器会有一个隐式转换。看下面的例子: package main import ( "fmt" ) func main() { var myInt int32 = 5 var myFloat float64 = 0 fmt.Println(myInt) fmt.Println(myFloat) } 对于myInt变量,它存储的就是int32类型的5;对于myFloat变量,它存储的是int64类型的0。或许您可能会写出这样的代码,但确实不是必须这么做的: package main import ( "fmt" ) func main() { var myInt int32 = int32(5) var myFloat float64 = float64(0) fmt.Println(myInt) fmt.Println(myFloat) } 在C中,大多数类型转换都是可以隐式进行的,比如: #include <stdio.h> int main(int argc,char **argv) { int uid = 12345; long gid = uid; printf("uid=%d,gid=%dn",uid,gid); return 0; } 但是在golang中,您不能这么做。有个类似的例子: package main import ( "fmt" ) func main() { var uid int32 = 12345 var gid int64 = int64(uid) fmt.Printf("uid=%d,gid) } 很显然,将uid赋值给gid之前,需要将uid强制转换成int64类型,否则会panic。golang中的类型区分静态类型和底层类型。您可以用type关键字定义自己的类型,这样做的好处是可以语义化自己的代码,方便理解和阅读。 package main import ( "fmt" ) type MyInt32 int32 func main() { var uid int32 = 12345 var gid MyInt32 = MyInt32(uid) fmt.Printf("uid=%d,51); margin-top:0px; margin-bottom:10px">在上面的代码中,定义了一个新的类型MyInt32。对于类型MyInt32来说,MyInt32是它的静态类型,int32是它的底层类型。即使两个类型的底层类型相同,在相互赋值时还是需要强制类型转换的。可以用reflect包中的Kind方法来获取相应类型的底层类型。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |