英文:
How to print a function that is passed as parameter to a function
问题
我知道如何在JavaScript中实现,它将类似于以下内容:
function describe(i) {
return String(i);
}
function dummyReducer(int) {
return 1;
}
function Accumulator(reducer, init) {
var input = {
"func_name": "accumulatorLoger",
"func_data": {
"reducer": describe(reducer),
"init": init
}
};
// TODO: 下一步:将输入数据保存在数据库中
console.log(input);
return dummyReducer;
}
请注意,这是对JavaScript代码的翻译,可能需要根据您的具体需求进行调整。
英文:
I know how to do in javascript, it will be something similar to:
The Go function will receive a function as parameter, I wanna get function as string to build a map that then I'll save in some database.
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
}
答案1
得分: 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
}
如果函数名称包含包限定符,你可以对其进行清理:
if i := strings.LastIndexByte(name, '.'); i >= 0 {
name = name[i+1:]
}
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")
}
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()
}
https://play.golang.org/p/QDMSMhwrf39
英文:
If you want the body you need the source. That means that your program will need access to the Go file in which the function you want the body of was declared.
To get a function's file, you can use (*runtime.Func).FileLine
. And you'll also need the name of the function later, so use the runtime information to get that too:
func getFuncInfo(f interface{}) (name, file string) {
pc := reflect.ValueOf(f).Pointer()
fn := runtime.FuncForPC(pc)
file, _ = fn.FileLine(pc)
return fn.Name(), file
}
The name of the function may be package-qualified, if so you should clean it up:
if i := strings.LastIndexByte(name, '.'); i >= 0 {
name = name[i+1:]
}
https://play.golang.org/p/63zwvOh1qzE
Once you have the file, and your program has access to it, you can parse it with go/parser.ParseFile
, retrieve the function's AST, and then print the body with 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")
}
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论