> --
> 官网: http://golang-china.org/
> IRC: irc.freenode.net #golang-china
> @golangchina
>
哎,现在就是用反射来解决了。v := reflect.ValueOf(i)if v.IsNil() {// xxxx}蛋疼啊,性能啊。
Under the covers, interfaces are implemented as two elements,
a type and a value. The value, called the interface's dynamic
value, is an arbitrary concrete value and the type is that of
the value. For the int value 3, an interface
value contains, schematically, (int, 3).
An interface value is nil only if the inner value
and type are both unset, (nil, nil).
In particular, a nil interface will always
hold a nil type. If we store a
pointer of type *int inside an interface
value, the inner type will be *int regardless of the value
of the pointer: (*int, nil).
Such an interface value will therefore be non-nil even when the
pointer inside is nil.
This situation can be confusing, and often arises when a nil value is stored inside
an interface value such as an error return:
func returnsError() error {
var p *MyError = nil
if bad() {
p = ErrBad
}
return p // Will always return a non-nil error.
}
If all goes well, the function returns a nil p,
so the return value is an error interface value holding
(*MyError, nil).
This means that if the caller compares the returned error to nil,
it will always look as if there was an error even if nothing bad
happened. To return a proper nil error to the caller, the
function must return an explicit nil:
func returnsError() error {
if bad() {
return ErrBad
}
return nil
}
It's a good idea for functions that return errors always to
use the error type in their signature
(as we did above) rather than a concrete type such as *MyError,
to help guarantee the error is created correctly. As an example, os.Open returns an error even though, if not nil,
it's always of concrete type *os.PathError.
Similar situations to those described here can arise whenever
interfaces are used. Just keep in mind that if any concrete
value has been stored in the interface, the interface will not
be nil.
For more information, see The
Laws of Reflection.
v := reflect.ValueOf(i)if v.IsNil() {// xxxx}
���۰�����������
��ʵ��ɲ���Ϊ��ν���ܲ���ô���ġ���û��ʵ�ʲ��Խ���֧���£�����˵�������Ŀ��������ƿ�����������prof������Ҳ�� �����ͷѲ��ˡ�����˵����reflect�Ϳ϶�Ӱ�����ܡ�
��ǰ����һ�����ѵ���Ŀ��Ҳ�dz������ܵĿ��ǣ��Ѻ��ĵIJ���ȫ���û����д��һ�飬���������һЩ�Ƚ��µ�ָ���д��֮��һ ���ԣ����ֱ�ԭ��c���Եİ汾�����߱����ܶ�ʱ����������Ϊ���Ż��ˣ���ʵ���治����������Ż��ء�
�������ӿڿ���֧������C#�ķ��;�ˬ�ˡ�
�� 2012��7��11�� ����11:04��steve wang <steve....@gmail.com>д ����
����ʹ�÷��������?��Ȼ���õ��ǿսӿڣ���Ȼ��Ҫת�ɾ������͵ġ�
���˸о����Ҳ��golang�ĸ����ԣ��������壩֮һ�ɡ�
func test(i interface{}) {
if i == nil {
fmt.Println("nil")
} else {
t := i.(*TT)
fmt.Println(t == nil)
> ���Կ�����ƪ���£���˵����http://runtime.sinaapp.com/?p=24
>
> 2012/7/11 lulu Lee <qlee...@gmail.com>
>
>> ���Դ��룺
>>
>> package main
>>
>> import "fmt"
>>
>> func main() {
>> type TT struct {}
>> var t *TT
>> test(t)
>> }
>>
>> func test(i interface{}) {
>> fmt.Printf("%v => %v", i, i == nil)
>> }
>>
>> ���ؽ��Ϊ��<nil> => false
>>
>> ���Ե�ַ�� http://play.golang.org/p/kDVSIna2Wd
>
> --
> ����: http://golang-china.org/
func NewTT() (tt *TT, err error) {
var p *MyError = nil
if bad() {
p = ErrBad
return new(TT), p
}
return nil, p // Will always return a non-nil error.
}
�Ҹ��˸о������ go ��̷�ʽ��̫�˽��ԭ������ġ�����д��ʮ�����е� go ���룬Ҳû��Ϊ�����������
����ͨ���ķ�ʽ�ǣ����һ��������ܳ��?��ôӦ�÷��� error�����磺
func NewTT() (tt *TT, err error) {...}
�õ�ʱ��
tt, err := NewTT()if err != nil {return}
... // tt ȷ�ϲ��� nil
v := reflect.ValueOf(i)if v.IsNil() {// xxxx}
���۰�����������
�������ӿڿ���֧������C#�ķ��;�ˬ�ˡ�
�� 2012��7��11�� ����11:04��steve wang <steve....@gmail.com>д ����
����ʹ�÷��������?��Ȼ���õ��ǿսӿڣ���Ȼ��Ҫת�ɾ������͵ġ�
���˸о����Ҳ��golang�ĸ����ԣ��������壩֮һ�ɡ�
func test(i interface{}) {
if i == nil {
fmt.Println("nil")
} else {
t := i.(*TT)
fmt.Println(t == nil)
> ���Կ�����ƪ���£���˵����http://runtime.sinaapp.com/?p=24
>
> 2012/7/11 lulu Lee <qlee...@gmail.com>
>
>> ���Դ��룺
>>
>> package main
>>
>> import "fmt"
>>
>> func main() {
>> type TT struct {}
>> var t *TT
>> test(t)
>> }
>>
>> func test(i interface{}) {
>> fmt.Printf("%v => %v", i, i == nil)
>> }
>>
> ����: http://golang-china.org/
这个问题确实不需要纠结, 如果NewTT方法是由信得过的人编写的话。要是不了解go的人写出如下的代码,就会导致上层调用者判断出错:
func NewTT() (tt *TT, err error) { var p *MyError = nil if bad() { p = ErrBad return new(TT), p } return nil, p // Will always return a non-nil error. }
于 2012年07月12日 09:53, shiwei xu 写道:
我个人感觉是你对 go 编程范式不太了解的原因引起的。我们写了十几万行的 go 代码,也没有为这个问题纠结过。
我们通常的方式是,如果一个函数可能出错,那么应该返回 error。比如:
func NewTT() (tt *TT, err error) {...}
用的时候:
tt, err := NewTT()if err != nil {return}
... // tt 确认不是 nil
在 2012年7月12日 上午1:12,lulu Lee <qlee...@gmail.com>写 道:
哎,现在就是用反射来 解决了。
v := reflect.ValueOf(i)if v.IsNil() {// xxxx}
蛋疼啊,性能啊。
另外如果接口可以支持类似C#的泛型就爽了。
在 2012年7月11日 下午11:04,steve wang <steve....@gmail.com>写 道:
可以使用反射来处理。既然你用的是空接口,自然是要转成具体类型的。
个人感觉这个也算golang的复杂性(或者陷阱)之一吧。
func test(i interface{}) {
if i == nil {
fmt.Println("nil")
} else {
t := i.(*TT)
fmt.Println(t == nil)
> 可以看看这篇文章,有说明,http://runtime.sinaapp.com/?p=24
>
> 2012/7/11 lulu Lee <qlee...@gmail.com>
>
>> 测试代码:
>>
>> package main
>>
>> import "fmt"
>>
>> func main() {
>> type TT struct {}
>> var t *TT
>> test(t)
>> }
>>
>> func test(i interface{}) {
>> fmt.Printf("%v => %v", i, i == nil)
>> }
>>
> 官网: http://golang-china.org/
再问一个问题,如果判断为nil怎样新建一个实例并赋值给原来的指针呢?package mainimport "fmt"import "reflect"func main() {type TT struct { a int }var t *TTtest(t)fmt.Printf("Result t: %s", t)}
--