问题:
在设计用于加载插件的 Go 模块中,必须确保主包中存在具有预定名称和签名的特定函数。如果此函数不存在或与预期签名不匹配,则需要一条描述性错误消息。给定一个函数类型变量,如何获取底层签名?
解决方案:
仅仅依靠reflect.Type.String()只提供类型的名称,例如main.ModuleInitFunc。要检索完整的签名,我们必须使用reflect.Type提供的信息手动构造它。
实现:
func signature(f interface{}) string { t := reflect.TypeOf(f) if t.Kind() != reflect.Func { return "<not a function>" } buf := strings.Builder{} buf.WriteString("func (") for i := 0; i < t.NumIn(); i++ { if i > 0 { buf.WriteString(", ") } buf.WriteString(t.In(i).String()) } buf.WriteString(")") if numOut := t.NumOut(); numOut > 0 { if numOut > 1 { buf.WriteString(" (") } else { buf.WriteString(" ") } for i := 0; i < t.NumOut(); i++ { if i > 0 { buf.WriteString(", ") } buf.WriteString(t.Out(i).String()) } if numOut > 1 { buf.WriteString(")") } } return buf.String() }
用法:
通过将函数变量传递给signature()函数,我们可以获得相应的签名作为字符串。例如:
var myFunc ModuleInitFunc fmt.Println(signature(func(i int) error { return nil })) fmt.Println(signature(myFunc)) fmt.Println(signature(time.Now)) fmt.Println(signature(os.Open)) fmt.Println(signature(log.New)) fmt.Println(signature(""))
输出:
func (int) error func (int) error func () time.Time func (string) (*os.File, error) func (io.Writer, string, int) *log.Logger <not a function>
注意:
认识到这是不可能的,这一点至关重要从签名中提取参数名称和结果类型,因为 Go 不存储或提供对其的访问信息。
以上是如何以字符串形式检索 Go 函数的签名?的详细内容。更多信息请关注PHP中文网其他相关文章!