分享一个项目:go `file_line`,在编译器得到源码行号,减少运行期runtime消耗

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


file_line

https://github.com/ahfuzhang/file_line

Like __FILE__/__LINE__ of C: use go generate to get source code line number at compile time.

像 C 语言里面的 __FILE__/__LINE__ 宏一样:在编译期,通过 go generate来得到源码行号。

我通常使用下面这个函数来获取源码的行号:

go 复制代码
func SourceCodeLoc(callDepth int) string {
	_, file, line, ok := runtime.Caller(callDepth)
	if !ok {
		return ""
	}
	file = strings.ReplaceAll(file, "\\", "/")
	arr := strings.Split(file, "/")
	if len(arr) > 3 {
		file = strings.Join(arr[len(arr)-3:], "/")
	}
	return fmt.Sprintf("%s:%d", file, line)
}

func example(){
     Mylogger.Infof("[%s]something happens here", SourceCodeLoc(1))
}

这里的 runtime.Caller() 实在程序运行期间去计算程序对应的源码行的,必然会带来性能损耗。

这种需求完全可以在编译期间实现,最终我发现使用 go ast 库能够简单的达成这一功能。

How to use

  1. 安装:

    go install github.com/ahfuzhang/file_line@latest

  2. 编写代码,在需要使用行号的地方使用这样的place holder:

go 复制代码
func myCode(){
    Mylogger.Infof("%s: something happens here", "[file.go:123]")
}
  1. 在程序的入口出加上 go generate指令:
go 复制代码
//go:generate file_line -src=./

func main() {
	fmt.Println("use a place holder:", "[file.go:123]")
}
  1. 在编译前执行 go generate
  • 所有的处于函数调用参数位置的 place holder 会被替换为正确的文件名和行号
  • 也可以直接在命令行执行 file_line -src=./
  1. 执行 go build

Have Fun. 😃