英文:
Golang pass nil value as an interface through reflection
问题
我有一个带有接口参数的函数:
func f(e error) {
if e == nil {
fmt.Println("YEY! NIL") // 如何到达这里?
} else {
fmt.Println("NOT NIL :(")
}
}
我如何通过reflect
传递一个nil
值,以便它通过== nil
检查?
方法一:
func main() {
rf := reflect.ValueOf(f)
nilArg := reflect.Zero(reflect.TypeOf((error)(nil))) // 报错:panic: reflect: Zero(nil)
rf.Call([]reflect.Value{nilArg})
}
方法二:
type MyError struct{}
func (e MyError) Error() string {
return ""
}
func main() {
rf := reflect.ValueOf(f)
nilArg := reflect.Zero(reflect.TypeOf(&MyError{})) // NOT NIL :(
rf.Call([]reflect.Value{nilArg})
}
第二种方法由于https://golang.org/doc/faq#nil_error而无法工作。
Playground: https://play.golang.org/p/V0bMSPcCKI
英文:
I have a function with interface argument:
func f(e error) {
if e == nil {
fmt.Println("YEY! NIL") // how to get here?
} else {
fmt.Println("NOT NIL :(")
}
}
How do I pass it a nil value via reflect
so that it passes == nil
check?
Approach 1:
func main() {
rf := reflect.ValueOf(f)
nilArg := reflect.Zero(reflect.TypeOf((error)(nil))) // panic: reflect: Zero(nil)
rf.Call([]reflect.Value{nilArg})
}
Approach 2:
type MyError struct{}
func (e MyError) Error() string {
return ""
}
func main() {
rf := reflect.ValueOf(f)
nilArg := reflect.Zero(reflect.TypeOf(&MyError{})) // NOT NIL :(
rf.Call([]reflect.Value{nilArg})
}
Second approach doesn't work due to https://golang.org/doc/faq#nil_error
Playground: https://play.golang.org/p/V0bMSPcCKI
答案1
得分: 6
使用表达式reflect.TypeOf((*error)(nil)).Elem()
来获取接口error
的reflect.Type
。
问题中的第一种方法不起作用,因为表达式reflect.TypeOf((error)(nil))
返回nil
。空接口值的具体类型是nil
。
关键是将非接口值传递给reflect.TypeOf()
,并使用反射方法从中获取所需的reflect.Type
。在这个答案中,我将*error
传递给reflect.TypeOf()
,并在结果上调用Elem
以获取error
的reflect.Type
。
使用以下代码创建nilArg
:
nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
英文:
Use the expression reflect.TypeOf((*error)(nil)).Elem()
to get the reflect.Type for interface error
.
The first approach in the question does not work because the expression reflect.TypeOf((error)(nil))
returns nil
. The concrete type of a nil interface value is nil.
The trick is to pass a non-interface value to reflect.TypeOf()
and use reflect methods to get the desired reflect.Type
from there. In this answer, I pass a *error
to reflect.TypeOf()
and call Elem
on the result to get the reflect.Type
for error
.
Use the following to create nilArg
:
nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
答案2
得分: 0
你有两个选择,基本上在函数f
的参数中,e
是(*MyError)(nil)
而不是nil
。所以要么将接口断言回MyError
类型,要么使用更多的反射来检查它是否为nil
。
e.(*MyError) == nil
或者
reflect.ValueOf(e).IsNil()
可运行的示例: https://play.golang.org/p/2KWguSx618
有用的链接:
-
https://stackoverflow.com/questions/13476349/check-for-nil-and-nil-interface-in-go
-
https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I/discussion
英文:
You have two options, basically e
in the arguments to function f
is (*MyError)(nil)
not nil
. So either assert the interface back to type MyError
or use more reflection to check if it's nil.
e.(*MyError) == nil
or
reflect.ValueOf(e).IsNil()
Runnable Example: https://play.golang.org/p/2KWguSx618
useful links:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论