在 Go单元测试——资源初始化 里获取配置文件的绝对路径时,提到了 Caller 方法。这个方法在日志打印的包中特别常见。
日志文件中记录的文件路径和行号,就是这个函数的返回值。

pc, file, line, ok := runtime.Caller(0)

翻看一些日志的开源包,可能就会看到这个方法的调用。如果全局没有搜索到的话,很可能是它组合调用了类似下面的自定义方法,想要获取更多的调用栈信息。对比 runtime.Caller
源码和我们自定义的 GetCallerFrame 方法,它们内部实现逻辑是完全一致的,只是返回值上做了处理。

func GetCallerFrame(skip int) runtime.Frame {rpc := make([]uintptr, 1)n := runtime.Callers(skip, rpc[:])if n < 1 {return runtime.Frame{}}frame, _ := runtime.CallersFrames(rpc).Next()return frame
}

通过 runtime.Frame 可以获取到调用栈的方法体信息,通过 frame.Function 我们可以获取很多有用的信息,比如当前调用的函数名、文件的路径、结构体的名称。如果你看过 panic 输出的调用栈信息的话,调用栈信息中显示的函数就是 frame.Function 。

我们将GetCallerFrame作为一个util类的方法,然后来实际说明一下.。其中,GetHistory中会调用util中的 GetCallerFrame 方法,我们看一下它的具体实现:


live.go 的代码如下,特别说明的是,目录的名称和包的声明不相同,目录名称为data,包名为dataPackage,主要是区分,caller最终输出的是目录的路径,而非包名。

函数体中skip传递 2 表示获取的是GetHistory的方法信息,递推的向上,0代表Caller本身,1代表封装它的函数GetCallerFrame,2就代表当前调用GetCallerFrame的函数。


执行结果输出:路径+结构体+方法名称,通过这个输出,我们可以提炼获取方法名称的函数:

local/awesomeProject3/data.(*Live).GetHistory

如果要变得更加通用一些,方法体中的常量2其实可以声明为 skip + 1,我们把 GetCallerFrame 当做我们代码意义上的 “Caller”。

// desc: 获取方法名称
func GetCallerFunction(skip ...int) string {s := 0if len(skip) != 0 {s = skip[0]}frame := GetCallerFrame(s + 1)function := ""if split := strings.LastIndexByte(frame.Function, '/'); split != -1 && split+1 < len(frame.Function) {function = frame.Function[split+1:]}if split := strings.IndexByte(function, '.'); split != -1 && split+1 < len(function) {function = function[split+1:]}return function
}

类似于获取路径、行号的就都很简单了

runtime Caller 方法再封装相关推荐

  1. 不要再封装各种Util工具类了,这个神级框架值得拥有!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! Hutool 谐音 "糊涂",寓意追求 ...

  2. iOS经典面试题之使用runtime associate方法关联的对象释放及dealloc底层原理

    一.题目分析 使用 runtime associate 方法关联的对象,需要在主对象 dealloc 的时候释放吗? 无论在 MRC 下还是 ARC 下均不需要,被关联的对象在生命周期内要比对象本身释 ...

  3. 加密封装 怎么把_不要再封装各种Util工具类了,这个神级框架值得拥有!

    Hutool 谐音 "糊涂",寓意追求 "万事都作糊涂观,无所谓失,无所谓得" 的境界. Hutool 是一个 Java 工具包,也只是一个工具包,它帮助我们简 ...

  4. httpurlconnection 封装_不要再封装各种Util工具类了,看看这个框架

    不要再封装各种Util工具类了,看看这个框架 Hutool 谐音 "糊涂",寓意追求 "万事都作糊涂观,无所谓失,无所谓得" 的境界.    Hutool 是一 ...

  5. Go学习——runtime.Caller()函数

    目录 函数: 参数解释: 例子: 函数: func Caller(skip int) (pc uintptr, file string, line int, ok bool) Caller()报告当前 ...

  6. golang runtime.Caller 学习笔记

    runtime.Caller runtime.Caller可以获取到调用时的代码文件路径.行数等信息,在打印日志时常常使用 runtime.Caller源码 // Caller reports fil ...

  7. java exec 路径_[Java] 关于java.lang.Runtime.exec()方法运行命令所在目录的探讨。 | 学步园...

    测试代码: import java.util.*; import java.io.*; publicclassBadExecJavac { publicstaticvoidmain(String ar ...

  8. Promise方法 理解 封装

    Promise是什么? Promise直接打印出来看看吧,console.dir(Promise),就这么简单粗暴 可以看出:Promise是一个构造函数.ES6中新增的. 从打印的结果可以看出 里面 ...

  9. 【类库】私房干货.Net数据层方法的封装

    [类库]私房干货.Net数据层方法的封装 作者:白宁超 时间:2016年3月5日22:51:47 摘要:继上篇<Oracle手边常用70则脚本知识汇总>文章的发表,引起很多朋友关注.便促使 ...

最新文章

  1. 衡量微型计算机的性能指标参数有哪些,衡量计算机性能的主要技术指标有哪些?...
  2. 区块链公司发现BCH团队比BTC团队更容易接近
  3. 问题小结(2)-dialog内容动态变化(调用系统方法时)
  4. 分布式中的 transaction log
  5. 计算从A地出发到各个地方的路径及距离
  6. php eot eod_EOD的完整形式是什么?
  7. 【英语学习】【Level 08】U05 Better option L5 A picture is worth a thousand words
  8. php面向对象受保护,php面向对象二之封装,protected ,public,private权限管理
  9. 扫地机器人单扫和双扫_评测 | 千元以下的扫拖一体机器人,到底值不值得买?...
  10. 惨遭打脸:字节某部门竟然有这么多测试
  11. CentOS6.5 firefox安装flash插件
  12. HBASE元数据及数据读取过程
  13. 第十二课,assimp模型加载(数据加载篇)
  14. 错误记录(Unindent amount does not match previous indent)
  15. 直播活动策划方案怎么做
  16. 服务器电脑的作用,什么是wins服务器及其作用 -电脑资料
  17. 双稳态电路的两个稳定状态是什么_555时基电路内部结构及其工作原理
  18. perf Examples
  19. 无法解析服务器的dns地址
  20. android模拟器定制,定制Android模拟器skin

热门文章

  1. Mac下解决硬盘无法读取问题Mounty for NTFS - 免费让 Mac 原生支持移动硬盘/U盘 NTFS 读写的必备驱动应用
  2. 计算机考试登记表是准考证嘛
  3. 导数卷积 牛客 NTT
  4. 设置浏览器谷歌/edge浏览器允许跨域
  5. mysql等保测评命令_Mysql等保部分加固
  6. 缺失值处理(Imputation)
  7. 计算机网络学生机怎样连接总机,极域课堂管理系统怎么连接老师 学生端连接问题解决方法...
  8. CSDN博客上传的图片水印去除
  9. Project-Euler-045思维
  10. java无响应_Java HttpClient请求无响应解决方案