go - 如何使用 Golang 的反射实例化 nil 错误?
问题描述
我正在使用 reflect.MakeFunc 编写一个函数。该函数可以返回错误。当它成功时,我希望它返回 nil 作为其错误类型的返回值。我如何使用反射来做到这一点?目前我有这个:
package main
import (
"fmt"
"reflect"
"errors"
)
func main() {
fmt.Println("Hello, playground")
f := func() error {return nil}
fn := reflect.MakeFunc(reflect.TypeOf(f), func(args []reflect.Value) []reflect.Value {
return []reflect.Value{reflect.New(reflect.TypeOf(errors.New("")))}
}).Interface().(func() error)
fmt.Printf("err: %v", fn())
}
我明白了panic: reflect: function created by MakeFunc using closure returned wrong type: have **errors.errorString for error
。我也尝试添加一个.Elem()
after reflect.New(reflect.TypeOf(errors.New("")))
,但我得到了panic: reflect: function created by MakeFunc using closure returned wrong type: have *errors.errorString for error
. 我试过.Elem().Elem()
了,我遇到了分段错误。
如何获得表示零错误的 reflect.Value?
解决方案
使用以下内容:
var nilError = reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
func main() {
fmt.Println("Hello, playground")
f := func() error { return nil }
fn := reflect.MakeFunc(reflect.TypeOf(f), func(args []reflect.Value) []reflect.Value {
return []reflect.Value{nilError}
}).Interface().(func() error)
fmt.Printf("err: %v", fn())
}
让我们分解一下。第一步是获取一个reflect.Type
for error
: reflect.TypeOf((*error)(nil)).Elem()
。更简单reflect.TypeOf((error)(nil))
的方法不起作用,因为参数的具体值是nil
。没有类型 fornil
也不是我们想要的类型。解决方法是传递一个指针error
,然后调用Elem()
类型来获取relfect.Type
for error
。
第二步是为该类型创建一个零值。