dongwo5940 2017-05-12 12:24
浏览 119
已采纳

Golang通过反射将nil值作为接口传递

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

  • 写回答

2条回答 默认 最新

  • dtsc14683 2017-05-12 12:47
    关注

    Use the following to create nilArg:

    nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
    

    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.

    playground example

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?