登录
首页 >  Golang >  Go问答

如何在go中获取函数的签名作为字符串

来源:Golang技术栈

时间:2023-04-15 20:51:26 411浏览 收藏

哈喽!大家好,很高兴又见面了,我是golang学习网的一名作者,今天由我给大家带来一篇《如何在go中获取函数的签名作为字符串》,本文主要会讲到golang等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! 下面就一起来看看吧!

问题内容

我正在实现一个加载 go 插件的 go 模块。

我假设主包上存在一个具有特定名称和特定签名的函数,并且希望有一个很好的错误消息,以防它找不到或与预期的签名不匹配。

给定一个具有函数类型的变量,如何获得该函数的底层签名?

以下仅打印类型的名称(例如main.ModuleInitFunc)而不是完整的签名。

package main

import "fmt"

type ModuleInitFunc func(someInt int) error

func main() {
    var myFunc ModuleInitFunc = nil

    fmt.Printf("%T", lol)
}

正确答案

reflect.Type.String()只返回类型名称,因此如果函数值具有命名类型,您将只会看到类型名称。请注意,如果函数值是函数文字(具有未命名的类型),这将打印函数的签名:

var myFunc ModuleInitFunc

fmt.Printf("%T\n", myFunc)
fmt.Printf("%T\n", func(i int) error { return nil })

输出(在Go Playground上试试):

main.ModuleInitFunc
func(int) error

如果类型是命名类型,我们必须自己构建签名,但幸运的是,它reflect.Type拥有我们需要的所有信息。

Type.In()返回第 i个参数的类型,同样Type.Out()返回第 i个结果类型的类型。

使用这些,这是一个返回函数值签名的示例实现:

func signature(f interface{}) string {
    t := reflect.TypeOf(f)
    if t.Kind() != reflect.Func {
        return ""
    }

    buf := strings.Builder{}
    buf.WriteString("func (")
    for i := 0; 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  0 {
                buf.WriteString(", ")
            }
            buf.WriteString(t.Out(i).String())
        }
        if numOut > 1 {
            buf.WriteString(")")
        }
    }

    return buf.String()
}

测试它:

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(""))

输出(在Go Playground上试试):

func (int) error
func (int) error
func () time.Time
func (string) (*os.File, error)
func (io.Writer, string, int) *log.Logger

请注意,不能同时打印参数和结果类型的名称,因为它们无法存储/访问。有关详细信息,请参阅[Go 中是否存在未命名参数?](https://stackoverflow.com/questions/40950877/is-unnamed- arguments-a-thing-in-go/40951013#40951013)

今天关于《如何在go中获取函数的签名作为字符串》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>