golang中interface判断nil问题
xiaohu50 · · 9717 次点击 · · 开始浏览interface数据的表示
在示例中,我们定义一个interface名为Stringer,同时定义一个符合其定义的Binary类型:
type
Stringer interface {String()
string}type
Binary uint64func
(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, 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为零值,即<itable, data>=<nil, nil>时,才能等于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将会被赋值成<nil, nil>的interface,可以用==nil来判断
- var b *Binary; isNil(b)将会输出judge2 输入的b被赋值成<type=*Binary, value=nil>类型的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被赋值成<type=Binary, value=Binary(0)类型的interface,而reflect.ValueOf(s)返回了具体类型的reflect.Value表示,此处即为Binary(0)的reflect.Value表示,而reflect.Value.isNil只接受" a
chan, func, interface, map, pointer, or slice value",故panic
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
interface数据的表示
在示例中,我们定义一个interface名为Stringer,同时定义一个符合其定义的Binary类型:
type
Stringer interface {String()
string}type
Binary uint64func
(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, 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为零值,即<itable, data>=<nil, nil>时,才能等于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将会被赋值成<nil, nil>的interface,可以用==nil来判断
- var b *Binary; isNil(b)将会输出judge2 输入的b被赋值成<type=*Binary, value=nil>类型的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被赋值成<type=Binary, value=Binary(0)类型的interface,而reflect.ValueOf(s)返回了具体类型的reflect.Value表示,此处即为Binary(0)的reflect.Value表示,而reflect.Value.isNil只接受" a
chan, func, interface, map, pointer, or slice value",故panic