Skip to content

Instantly share code, notes, and snippets.

@ecoshub
Last active July 16, 2023 00:10
Show Gist options
  • Save ecoshub/eeed3adc1ee9ee1c525bba8143343f61 to your computer and use it in GitHub Desktop.
Save ecoshub/eeed3adc1ee9ee1c525bba8143343f61 to your computer and use it in GitHub Desktop.
get function info including comment / doc section
package main
import (
"errors"
"fmt"
"go/ast"
"go/doc"
"go/parser"
"go/token"
"path/filepath"
"reflect"
"runtime"
"strings"
)
// Info minimal info struct for function
type Info struct {
FilePath string
FunctionName string
Comment string
FunctionLine int
}
// function main
// this is the first line of comment
// this is the second line of comment
func main() {
c, err := GetFunctionInfo(main)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("FilePath:", c.FilePath)
fmt.Println("FunctionName:", c.FunctionName)
fmt.Println("FunctionLine:", c.FunctionLine)
fmt.Println("Comment:", c.Comment)
}
func GetFunctionInfo(f interface{}) (*Info, error) {
ffpc := runtime.FuncForPC(reflect.ValueOf(f).Pointer())
if ffpc == nil {
return nil, errors.New("error. function program counter is nil")
}
filePath, functionLine := ffpc.FileLine(0)
fset := token.NewFileSet()
parsedAst, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
if err != nil {
return nil, err
}
tokens := strings.Split(ffpc.Name(), ".")
if len(tokens) != 2 {
return nil, errors.New("error. func name split failed")
}
funcName := tokens[1]
importPath, err := filepath.Abs("/")
if err != nil {
return nil, err
}
pkg := &ast.Package{
Files: map[string]*ast.File{filePath: parsedAst},
}
myDoc := doc.New(pkg, importPath, doc.AllDecls)
for _, theFunc := range myDoc.Funcs {
if theFunc.Name == funcName {
return &Info{
FilePath: filePath,
FunctionName: funcName,
Comment: theFunc.Doc,
FunctionLine: functionLine,
}, nil
}
}
return nil, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment