golang中interface判断nil问题

interface数据的表示

参阅http://research.swtch.com/interfaces

在示例中,我们定义一个interface名为Stringer,同时定义一个符合其定义的Binary类型:

type Stringer  interface  {
     String() string
}
 
 
type Binary uint64
 
func (i Binary) String() string {
     return  strconv.Uitob64(i.Get(),  2 )
}
 
func (i Binary) Get() uint64 {
     return  uint64(i)
}
 
func ToString(any  interface {}) string {
     if  v, ok := any.(Stringer); ok {
         return  v.String()
     }
     switch  v := any.(type) {
     case  int :
         return  strconv.Itoa(v)
     case  float :
         return  strconv.Ftoa(v,  'g' , - 1 )
     }
     return  "???"
}

 

如果将一个Binary类型的变量b b=Binary(200)赋值给一个interface类型的值,排除内存优化的因素,将会形成以下的结构:

可以看到,interface变量由代表类型的itable和代表值的data来表示
itable中保留的仅有Stringer类型包含的方法,其余Binary的方法并不在interface变量中可见。
data变量保存的是原数据b的一份拷贝,而不是简单的引用。

Golang中的nil:

由定义可知:

var nil Type // Type must be a pointer, channel, func, interface, map, or slice type

nil is a predeclared identifier representing the zero value for a pointer, channel, func, interface, map, or slice type.

 

判断interface为nil:

只有当interface为零值,即=时,才能等于nil。

在上面的例中,如有有这样一个方法:

func isNil(s Stringer) {
         defer func() {
                 if  e := recover(); e != nil {
                         fmt.Printf( "panic in isNil(), err:%v\n" , e)
                 }  
         }()
         if  s == nil {
                 fmt.Printf( "judge1:s(%v) == nil\n" , s)
                 return
         }  
         if  reflect.ValueOf(s).IsNil() {
                 fmt.Printf( "judge2:s(%v) reflect nil\n" , s)
                 return
         }  
         fmt.Printf( "s(%v) pass\n" , s)
}
  • isNil(nil)将会输出judge1  输入的nil将会被赋值成的interface,可以用==nil来判断
  • var b *Binary; isNil(b)将会输出judge2 输入的b被赋值成类型的interface(*Binary和Binary都能满足Stringer接口定义),不能==nil,而reflect.ValueOf(s)返回了具体类型的reflect.Value表示,此处即为*Binary的reflect.Value表示,isNil接受interface类型判断为nil
  • var b Binary; isNil(b)将会输出panix in isNil() 输入的b被赋值成

你可能感兴趣的:(golang)