不得不知道的golang知识点之nil
golang中的
//nilisapredeclaredidentifierrepresentingthezerovaluefora//pointer,channel,func,interface,map,orslicetype.//Typemustbeapointer,orslicetypevarnilType //Typeishereforthepurposesofdocumentationonly.Itisastand-in//foranyGotype,butrepresentsthesametypeforanygivenfunction//invocation.typeTypeint nil的零值按照Go语言规范,任何类型在未初始化时都对应一个零值:布尔类型是false,整型是0,字符串是"",而指针、函数、interface、slice、channel和map的零值都是nil。 PS:这里没有说结构体struct的零值为nil,因为struct的零值与其属性有关
packagemain funcmain(){ //明确. _=(*struct{})(nil) _=[]int(nil) _=map[int]bool(nil) _=chanstring(nil) _=(func())(nil) _=interface{}(nil) //隐式. var_*struct{}=nil var_[]int=nil var_map[int]bool=nil var_chanstring=nil var_func()=nil var_interface{}=nil } 如果关注过golang关键字的同学就会发现,里面并没有 packagemainimport"fmt"funcmain(){ nil:=123 fmt.Println(nil)//123 var_map[string]int=nil//cannotusenil(typeint)astypemap[string]intinassignment } nil类型的地址和值大小
packagemain import( "fmt" ) funcmain(){ varmmap[int]string varptr*int varsl[]int fmt.Printf("%pn",m)//0x0 fmt.Printf("%pn",ptr)//0x0 fmt.Printf("%pn",sl)//0x0 } 业务中一般将 packagemain import( "fmt" "unsafe" ) funcmain(){ varp*struct{}=nil fmt.Println(unsafe.Sizeof(p))//8 vars[]int=nil fmt.Println(unsafe.Sizeof(s))//24 varmmap[int]bool=nil fmt.Println(unsafe.Sizeof(m))//8 varcchanstring=nil fmt.Println(unsafe.Sizeof(c))//8 varffunc()=nil fmt.Println(unsafe.Sizeof(f))//8 variinterface{}=nil fmt.Println(unsafe.Sizeof(i))//16 } 大小是编译器和体系结构所依赖的。以上打印结果为64位体系结构和正式 Go 编译器。对于32位体系结构,打印的大小将是一半。 对于正式 Go 编译器,同一种类的不同类型的两个nil值的大小始终相同。例如,两个不同的切片类型 ( []int和[]string) 的两个nil值始终相同。 nil值比较1.不同类型的 packagemain import( "fmt" ) funcmain(){ varmmap[int]string varptr*int fmt.Printf(m==ptr)//invalidoperation:m==ptr(mismatchedtypesmap[int]stringand*int) } 在 Go 中,两个不同可比较类型的两个值只能在一个值可以隐式转换为另一种类型的情况下进行比较。具体来说,有两个案例两个不同的值可以比较:
packagemain import( "fmt" ) funcmain(){ typeIntPtr*int fmt.Println(IntPtr(nil)==(*int)(nil)) //true fmt.Println((interface{})(nil)==(*int)(nil)) //false } 2.同一类型的两个 packagemain import( "fmt" ) funcmain(){ varv1[]int=nil varv2[]int=nil fmt.Println(v1==v2) fmt.Println((map[string]int)(nil)==(map[string]int)(nil)) fmt.Println((func())(nil)==(func())(nil)) }
packagemain import( "fmt" ) funcmain(){ fmt.Println((map[string]int)(nil)==nil)//true fmt.Println((func())(nil)==nil) //true } 3.两 如果两个比较的nil值之一是一个接口值,而另一个不是,假设它们是可比较的,则比较结果总是 false。原因是在进行比较之前,接口值将转换为接口值的类型。转换后的接口值具有具体的动态类型,但其他接口值没有。这就是为什么比较结果总是错误的。 packagemain import( "fmt" ) funcmain(){ fmt.Println((interface{})(nil)==(*int)(nil))//false } 常见问题1.函数返回 funcnilReturn()(string,error){ returnnil,nil//cannotusenilastypestringinreturnargument } 因为 2.map的nil key map的key为指针、函数、interface、slice、channel和map,则key可以为nil。 packagemain import( "fmt" ) funcmain(){ mmap:=make(map[*string]int,4) a:="a" mmap[&a]=1 mmap[nil]=99 fmt.Println(mmap)//map[0xc042008220:1<nil>:99] } 总结nil之所以比较难以理解因为我们经常混淆了nil值和nil类型,希望各位同学细细品味其中区别。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |