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

huangapple go评论84阅读模式
英文:

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

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

huangapple
  • 本文由 发表于 2021年8月20日 06:33:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/68855125.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定