不得不知道的golang知识点之nil
golang中的
// nil is a predeclared identifier representing the zero value for a // pointer,channel,func,interface,map,or slice type. // Type must be a pointer,or slice type var nil Type // Type is here for the purposes of documentation only. It is a stand-in // for any Go type,but represents the same type for any given function // invocation. type Type int nil的零值按照Go语言规范,任何类型在未初始化时都对应一个零值:布尔类型是false,整型是0,字符串是"",而指针、函数、interface、slice、channel和map的零值都是nil。 PS:这里没有说结构体struct的零值为nil,因为struct的零值与其属性有关
package main func main() { // 明确. _ = (*struct{})(nil) _ = []int(nil) _ = map[int]bool(nil) _ = chan string(nil) _ = (func())(nil) _ = interface{}(nil) // 隐式. var _ *struct{} = nil var _ []int = nil var _ map[int]bool = nil var _ chan string = nil var _ func() = nil var _ interface{} = nil } 如果关注过golang关键字的同学就会发现,里面并没有 package main import "fmt" func main() { nil := 123 fmt.Println(nil) // 123 var _ map[string]int = nil //cannot use nil (type int) as type map[string]int in assignment } nil类型的地址和值大小
package main import ( "fmt" ) func main() { var m map[int]string var ptr *int var sl []int fmt.Printf("%pn",m) //0x0 fmt.Printf("%pn",ptr ) //0x0 fmt.Printf("%pn",sl ) //0x0 } 业务中一般将 package main import ( "fmt" "unsafe" ) func main() { var p *struct{} = nil fmt.Println( unsafe.Sizeof( p ) ) // 8 var s []int = nil fmt.Println( unsafe.Sizeof( s ) ) // 24 var m map[int]bool = nil fmt.Println( unsafe.Sizeof( m ) ) // 8 var c chan string = nil fmt.Println( unsafe.Sizeof( c ) ) // 8 var f func() = nil fmt.Println( unsafe.Sizeof( f ) ) // 8 var i interface{} = nil fmt.Println( unsafe.Sizeof( i ) ) // 16 } 大小是编译器和体系结构所依赖的。以上打印结果为64位体系结构和正式 Go 编译器。对于32位体系结构,打印的大小将是一半。 对于正式 Go 编译器,同一种类的不同类型的两个nil值的大小始终相同。例如,两个不同的切片类型 ( []int和[]string) 的两个nil值始终相同。 nil值比较1.不同类型的 package main import ( "fmt" ) func main() { var m map[int]string var ptr *int fmt.Printf(m == ptr) //invalid operation: m == ptr (mismatched types map[int]string and *int) } 在 Go 中,两个不同可比较类型的两个值只能在一个值可以隐式转换为另一种类型的情况下进行比较。具体来说,有两个案例两个不同的值可以比较:
package main import ( "fmt" ) func main() { type IntPtr *int fmt.Println(IntPtr(nil) == (*int)(nil)) //true fmt.Println((interface{})(nil) == (*int)(nil)) //false } 2.同一类型的两个 package main import ( "fmt" ) func main() { var v1 []int = nil var v2 []int = nil fmt.Println(v1 == v2) fmt.Println((map[string]int)(nil) == (map[string]int)(nil)) fmt.Println((func())(nil) == (func())(nil)) }
package main import ( "fmt" ) func main() { fmt.Println((map[string]int)(nil) == nil) //true fmt.Println((func())(nil) == nil) //true } 3.两 如果两个比较的nil值之一是一个接口值,而另一个不是,假设它们是可比较的,则比较结果总是 false。原因是在进行比较之前,接口值将转换为接口值的类型。转换后的接口值具有具体的动态类型,但其他接口值没有。这就是为什么比较结果总是错误的。 package main import ( "fmt" ) func main() { fmt.Println( (interface{})(nil) == (*int)(nil) ) // false } 常见问题1.函数返回 func nilReturn() (string,error) { return nil,nil //cannot use nil as type string in return argument } 因为 2.map的nil key map的key为指针、函数、interface、slice、channel和map,则key可以为nil。 package main import ( "fmt" ) func main() { 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类型,希望各位同学细细品味其中区别。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- perl – 从SVN集成中自定义Slack中显示的消息
- [Golang] 从零开始写Socket Server(6)【完结】
- delphi 数据库之不用数据源 以access为例(其他未
- vb.net – 在.NET环境中编译VB6代码
- 572. Subtree of Another Tree
- 《Programming in Lua 3》读书笔记(十一)
- delphi – 什么可能导致编译器不生成控制台输出
- Not found:org.codehaus.groovy.tools.GroovySta
- Perl中的字符串长度,与字符编码无关
- 字符串驱动技术—— MethodAddress , MethodName