2

I know how to do in javascript, it will be something similar to:

log function in javascript

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
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Romel Gomez
  • 325
  • 2
  • 19
  • 7
    You want to print the body of the function? Go is a compiled language, the source code is not available in the executable binary (unlike Javascript which is an interpreted language). – icza Aug 19 '21 at 22:45
  • 4
    Go is a compiled language. You cannot get the source from the compiled code. – Burak Serdar Aug 19 '21 at 22:46
  • Thanks for info @icza and Burak Serdar. Yes icza, I wanted to have the function code that is passed as parameter to then make tests cases with the data recolected, and build a better Accumulator function. The accumulator function pass some basic tests that I build, but not all the test pass when I send the code. So I have this idea of save the input in order to build a better function. – Romel Gomez Aug 19 '21 at 23:05
  • 1
    @Chiheb Nexus Yes, I need the full body. To get the signature of the functions, I found this question: https://stackoverflow.com/questions/54129042/how-to-get-a-functions-signature-as-string-in-go – Romel Gomez Aug 19 '21 at 23:09
  • 1
    I have the feeling that you’re too hung up with the idea of how to solve a problem the way you already know. Perhaps you should explain the problem (not the solution) and you will see there are probably other ways to solve it. – Edwin Dalorzo Aug 20 '21 at 04:26
  • 1
    [Don't paste images of code](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors) – Jonathan Hall Aug 20 '21 at 08:11

1 Answers1

6

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

mkopriva
  • 35,176
  • 4
  • 57
  • 71