使用反射在 Golang 中将 nil 值作为接口传递

3

我有一个带有接口参数的函数:

func f(e error) {
    if e == nil {
        fmt.Println("YEY! NIL") // how to get here?
    } else {
        fmt.Println("NOT NIL :(")
    }
}

如何通过reflect传递空值,以便它可以通过== nil检查?

方法1:

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,第二种方法不起作用。

演示示例:https://play.golang.org/p/V0bMSPcCKI


为什么 rf := reflect.ValueOf(f) 是必须的?&MyError{} 无论如何都不是 nil。 - Sarath Sadasivan Pillai
2个回答

6
使用表达式reflect.TypeOf((*error)(nil)).Elem()来获取接口error的reflect.Type。
问题中的第一种方法不起作用,因为表达式reflect.TypeOf((error)(nil))返回了nil。空接口值的具体类型是nil。
要想得到所需的reflect.Type,需要将非接口值传递给reflect.TypeOf()并使用反射方法。在这个答案中,我将*error传递给reflect.TypeOf()并在结果上调用Elem来获取errorreflect.Type
使用以下内容创建nilArg
nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())

playground example


0

有价值的信息,然而问题是关于传递nil参数,而不是更改函数内部的检查。 - Grozz
感谢您的澄清,很高兴您找到了答案! - Zak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接