nil是什么类型的数据

109 views
Skip to first unread message

damon.chen

unread,
May 18, 2014, 11:41:44 PM5/18/14
to Golang-China
Hi, all:

golang里面的nil把我给搞混了。

作为interface{}可以接受任意类型的值,当然也包括nil。

从上面nil是一个值,是值必然有一个类型,是一个类型,按理说必然应该支持type assertion。

但是go标准明确规定nil是不支持type assertion http://golang.org/ref/spec#Type_assertions

从规范上,我们可以做出上面的规范,但从语言的一致性上考虑,nil似乎是一个两面派,一方面他是一个值的数据信息,另一方面他没有值的那个类型 信息。为何go会这么设计?而不是设计为nil.(type assertion)就返回一个false错误信息呢?

从工程实践上,如果我有一个map[string]interface{}的时候,在取出interface{}值的时候,我不仅仅需要先判断值 是否为nil,然后才可以做type assertion,这可以认为是人为设置了编程的障碍么?





2014-5-19

steve wang

unread,
May 19, 2014, 2:16:40 AM5/19/14
to golang...@googlegroups.com
nil有类型,它表示某个类型的空值,它的具体类型可以从上下文中推导出来。
对于map[string]interface{},如果你的程序允许放进去一个nil(它的类型是interface{}),那么取出来的时候自然要判断非空。

刘蕴唐

unread,
May 19, 2014, 9:24:55 PM5/19/14
to golang...@googlegroups.com, damon.chen

nil应该是关键字,类似于iota

Sent with AquaMail for Android
http://www.aqua-mail.com

--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛中的“Golang-China”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/53797D78.6030303%40gmail.com
要查看更多选项,请访问https://groups.google.com/d/optout

Larry Li

unread,
May 19, 2014, 10:37:14 PM5/19/14
to golang...@googlegroups.com
http://golang.org/doc/faq#nil_error
In particular, a nil interface will always hold a nil type. 


要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/537aaee9.6eb7420a.6ce8.6e0b%40mx.google.com
要查看更多选项,请访问https://groups.google.com/d/optout

David DENG

unread,
Jun 6, 2014, 6:30:50 PM6/6/14
to golang...@googlegroups.com

damon.chen

unread,
Jun 6, 2014, 10:41:50 PM6/6/14
to golang...@googlegroups.com
是的,我发现的问题如果这么处理,就异常了

vl := i.(int)

那既然如此,为何不支持这样的返回结果,一定要求有一个ok处理,不是更强壮一些(go是一门工程语言)。


2014-06-07



于 2014/6/7 6:30, David DENG 写道:
David

On Sunday, May 18, 2014 8:41:44 PM UTC-7, Damon Chen wrote:
Hi, all:

golang里面的nil把我给搞混了。

作为interface{}可以接受任意类型的值,当然也包括nil。

从上面nil是一个值,是值必然有一个类型,是一个类型,按理说必然应该支持type assertion。

但是go标准明确规定nil是不支持type assertion http://golang.org/ref/spec#Type_assertions

从规范上,我们可以做出上面的规范,但从语言的一致性上考虑,nil似乎是一个两面派,一方面他是一个值的数据信息,另 一方面他没有值的那个类型 信息。为何go会这么设计?而不是设计为nil.(type assertion)就返回一个false错误信息呢?

从工程实践上,如果我有一个map[string]interface{}的时候,在取出interface{}值 的时候,我不仅仅需要先判断值 是否为nil,然后才可以做type assertion,这可以认为是人为设置了编程的障碍么?





2014-5-19
--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛中的“Golang-China”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china...@googlegroups.com

David DENG

unread,
Jun 8, 2014, 1:10:16 AM6/8/14
to golang...@googlegroups.com
vl := i.(int) 的写法通常在正常逻辑 i 里面的对象就应该是一个 int 的情况下才使用,如果里面的类型不是 int(nil 是无类型的,自然也不是 int)则会作为非正常状况,从而 panic。

vl, ok := i.(int) 的写法,则是程序逻辑很不确定 i 里面的类型是否为 int,需要实时做判断的情况,此时第一件事情是检查 ok 是否为 true,这就类似于一些语言里面进行 instanceof 的判断一样。

这里 nil 就是一个类型为空内容也为空的取值,在接口的使用上并没有特殊的对待。这在工程上不就是最方便的么?
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china+unsubscribe@googlegroups.com

damon.chen

unread,
Jun 8, 2014, 4:53:36 AM6/8/14
to golang...@googlegroups.com

于 2014/6/8 13:10, David DENG 写道:
vl := i.(int) 的写法通常在正常逻辑 i 里面的对象就应该是一个 int 的情况下才使用,如果里面的类型不是 int(nil 是无类型的,自然也不是 int)则会作为非正常状况,从而 panic。


这个正常的逻辑,不知道算什么样的正常逻辑?既然明确是一个int对象,还需要vl := i.(int),不觉得这是一个无聊的操作么?


vl, ok := i.(int) 的写法,则是程序逻辑很不确定 i 里面的类型是否为 int,需要实时做判断的情况,此时第一件事情是检查 ok 是否为 true,这就类似于一些语言里面进行 instanceof 的判断一样。

这里 nil 就是一个类型为空内容也为空的取值,在接口的使用上并没有特殊的对待。这在工程上不就是最方便的么?

On Friday, June 6, 2014 7:41:50 PM UTC-7, Damon Chen wrote:
是的,我发现的问题如果这么处理,就异常了

vl := i.(int)

那既然如此,为何不支持这样的返回结果,一定要求有一个ok处理,不是更强壮一些(go是一门工程语言)。


2014-06-07


于 2014/6/7 6:30, David DENG 写道:
David

On Sunday, May 18, 2014 8:41:44 PM UTC-7, Damon Chen wrote:
Hi, all:

golang里面的nil把我给搞混了。

作为interface{}可以接受任意类型的值,当然也包括nil。

从上面nil是一个值,是值必然有一个类型,是一个类型,按理说必然应该支持type assertion。

但是go标准明确规定nil是不支持type assertion http://golang.org/ref/spec#Type_assertions

从规范上,我们可以做出上面的规范,但从语言的一致性上考虑,nil似乎是一个两面派,一方面他 是一个值的数据信息,另 一方面他没有值的那个类型 信息。为何go会这么设计?而不是设计为nil.(type assertion)就返回一个false错误信息呢?

从工程实践上,如果我有一个map[string]interface{}的时候,在取出 interface{}值 的时候,我不仅仅需要先判断值 是否为nil,然后才可以做type assertion,这可以认为是人为设置了编程的障碍么?





2014-5-19
--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛中的“Golang-China”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china+unsubscribe@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/b21a50ac-d01e-48ff-ace3-e42f26623273%40googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout
--
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina
---
您收到此邮件是因为您订阅了Google网上论坛中的“Golang-China”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/06baebf7-5ea0-413b-9ea0-738b3b7a520c%40googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

Kun Li

unread,
Jun 8, 2014, 6:13:18 AM6/8/14
to golang...@googlegroups.com

2014-06-08 16:53 GMT+08:00 damon.chen <net...@gmail.com>:
这个正常的逻辑,不知道算什么样的正常逻辑?既然明确是一个int对象,还需要vl := i.(int),不觉得这是一个无聊的操作么?

你没理解他的意思。即使你确定interface里面是int对象,还是要用vl := i.(int)取出来。David的意思是你一般只会知道i里面是int对象的时候才用这个,比如已经判断type了。这个和nil是很难混淆的,所以没必要专门加一个ok option来出了

----------------------------------------------------------------------------------
Yours Sincerely
Kun

gplus.to/kunli

Damon Zhao

unread,
Jun 8, 2014, 6:17:28 AM6/8/14
to golang...@googlegroups.com
他说的明确类型是指你明确类型的情况  http://play.golang.org/p/owGcH5pUns

在 2014年6月8日星期日UTC+8下午4时53分36秒,Damon Chen写道:
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china+unsubscribe@googlegroups.com

Damon Zhao

unread,
Jun 8, 2014, 6:22:04 AM6/8/14
to golang...@googlegroups.com
对,就是这个意思,即使你确定你也得通过 assertion 取出来,不过碰到个函数返回 map[T][]T 你就麻烦了,这样即使你知道它里面的数据,比如 map[string][]string,你也不能 vl := i.(map[string][]string),必须得遍历 map,一个个做 assertion 才能取出来,论泛型的重要性:)

在 2014年6月8日星期日UTC+8下午6时13分18秒,Kun Li写道:

ubunoon

unread,
Jun 8, 2014, 10:17:28 AM6/8/14
to Golang-China
你的这个例子并不具有说明性,B也可以返回一个nil,从语法结构上,B返回nil的时候永远不会有编译问题。

同时在复杂的代码中,你有时候可能很难保证B返回的不是nil,这个时候明晃晃的使用i.(int),是非常危险的行为。比方说你从map[string]interface{}中取值,然后正好符合你的B返回值,但A中还是会异常。

我估计将来的go语言编写规范中,会增加一条 i.(int) 一定要强制要求写成 v, ok := i.(int)




要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/golang-china/9f3d71e3-18bc-4c17-a674-f76c45b4b506%40googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout



--
DamonChen
让生活更俏皮些

chai2010

unread,
Jun 8, 2014, 10:33:15 AM6/8/14
to golang中文小组
Go如果需要觉得安全的话, 那指针和unsafe包也得去掉吧.

我觉得绝对安全并不是什么好的特性.
我比较喜欢 x := v.(int) 和 x, ok := v.(int) 这种特性.
map中也是 x := m[42] 和 x, ok := m[42]


David DENG

unread,
Jun 8, 2014, 11:00:30 AM6/8/14
to golang...@googlegroups.com
  1. 解释一下我所说的所谓正常逻辑大部分情况下指的是就是如果程序没有 bug,就会成立的逻辑;如果出现了非正常的情况,通常整个代码的上下文比较难以处理这种情况(否则就不叫非正常的逻辑),所以最好的办法就是 panic。Go 中的 panic 是比通常 Java/C++ 中的 exception 更为严重的错误,因为 Go 通常不用 panic 来进行错误/失败操作的处理,而采用返回 error 的方式。
  2. 至于不能把 map[T][]T 直接 assert 成 map[string][]string ,则是因为在数据底层,这俩数据结构就是不一样的,所以这样的转换不是 trivial 的,以 Go 的设计理念,自然不会支持这样的转换。换句话说,这样的转换编译器来做也要重建一个 map,同时一个一个的 assert,快不了,那还不如你自己做,类似的问题在 FAQ 里面解释过:http://golang.org/doc/faq#convert_slice_of_interface

David DENG

unread,
Jun 8, 2014, 11:03:26 AM6/8/14
to golang...@googlegroups.com
有很多情况,根据附近的代码可以比较明确的知道 i 里面一定是一个 int(除非发生了 race 或者编译器有 bug),这时候 i.(int) 还是很有用的。

死的规范不是目的,最终是为了程序的可读性和可维护性。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到golang-china+unsubscribe@googlegroups.com
Reply all
Reply to author
Forward
0 new messages