如何打印作为参数传递给函数的函数

Rom*_*mez 2 go

我知道如何用 javascript 来做,它会类似于:

JavaScript 中的日志函数

Go 函数将接收一个函数作为参数,我想获取函数作为字符串来构建一个地图,然后将其保存在某个数据库中。

package main

import (
    "fmt"
)

func describe(i interface{}) string {
    return fmt.Sprintf("%v", i)
}

func dummyReducer(int) int {
    return 1
}

func Accumulator(reducer func(int, int) int, init int) func(int) int {

    input := map[string]interface{}{
        "func_name": "accumulatorLoger",
        "func_data": map[string]interface{}{
            "reducer": string(describe(reducer)),
            "init":    init,
        },
    }

    // {
    //  func_data: { init: 10, reducer: '0x64b880' },
    //  func_name: 'accumulatorLoger'
    // }

    // TODO: next: save the input data in the database
    fmt.Println(input)

    return dummyReducer
}
Run Code Online (Sandbox Code Playgroud)

mko*_*iva 6

如果你想要身体,你就需要源头。这意味着您的程序将需要访问声明了您想要的函数主体的 Go 文件。


要获取函数的文件,您可以使用(*runtime.Func).FileLine. 稍后您还需要函数的名称,因此也可以使用运行时信息来获取该名称:

func getFuncInfo(f interface{}) (name, file string) {
    pc := reflect.ValueOf(f).Pointer()
    fn := runtime.FuncForPC(pc)
    file, _ = fn.FileLine(pc)
    return fn.Name(), file
}
Run Code Online (Sandbox Code Playgroud)

函数的名称可能是包限定的,如果是这样,您应该清理它:

if i := strings.LastIndexByte(name, '.'); i >= 0 {
    name = name[i+1:]
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/63zwvOh1qzE


一旦您拥有该文件,并且您的程序可以访问它,您可以使用 解析它go/parser.ParseFile,检索函数的 AST,然后使用 打印正文go/printer.Fprint

func getFuncAST(funcname, filename string) (*ast.FuncDecl, *token.FileSet) {
    fs := token.NewFileSet()
    file, err := parser.ParseFile(fs, filename, "", 0)
    if err != nil {
        panic(err)
    }

    for _, d := range file.Decls {
        if f, ok := d.(*ast.FuncDecl); ok && f.Name.Name == funcname {
            return f, fs
        }
    }

    panic("function not found")
}
Run Code Online (Sandbox Code Playgroud)
func getFuncBodyString(f *ast.FuncDecl, fs *token.FileSet) string {
    var buf bytes.Buffer
    if err := printer.Fprint(&buf, fs, f.Body); err != nil {
        panic(err)
    }
    return buf.String()
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/QDMSMhwrf39