内容简介:今天和同事一起看了一个很诡异的问题,研究了半天发现是由于Go的编译缓存导致的,记录下来方便其他遇到问题的同学参考。首先编写一个hello.go文件,里面调用了C函数:对应的libhello.h文件:
今天和同事一起看了一个很诡异的问题,研究了半天发现是由于 Go 的编译缓存导致的,记录下来方便其他遇到问题的同学参考。
首先编写一个hello.go文件,里面调用了C函数:
package main /* #include "./libhello.c" */ import "C" import "fmt" func main() { fmt.Println(C.hello()) }
对应的libhello.h文件:
#ifndef _LIBHELLO_ # define _LIBHELLO_ # ifdef __cplusplus extern "C" { # endif int hello(); # ifdef __cplusplus } # endif #endif
以及libhello.c文件:
#include "libhello.h" int hello() { return 1; }
接下来用go build hello.go编译,执行./hello,输出结果为1,一切正常。
这时候,我们修改libhello.c文件,让hello()函数return 2。然后重新用go build hello.go编译,执行./hello,你会发现, 输出结果仍然为1 。
显然,cgo没有重新编译修改后的C代码。我们就想,干脆先用gcc编译成静态库,然后Go代码里面链接这个库,这样是不是就可以保证每次都使用最新代码了?于是,代码改成了这个样子:
package main /* #cgo LDFLAGS: -lhello -L. #include "./libhello.h" */ import "C" import "fmt" func main() { fmt.Println(C.hello()) }
然后我们先把C代码编译成静态库,再编译Go文件:
gcc -c libhello.c ar rcs libhello.a libhello.o go build hello.go
接着,我们修改libhello.c文件,让hello()函数return 2。然后重新用go build hello.go编译,执行./hello,不幸的是, 输出结果仍然为1 。
那么问题到底出在哪里呢?我们在go build的时候加上-x -v参数看看:
可以发现,这里有个cache。我们用nm来看一下这个cache的内容:
发现了吧?这就是我们的libhello.o。如果你只修改C文件,不修改Go文件,那么就会一直使用这个cache。。。
Google了一下发现,早就有人遇到过这个问题了: https://github.com/golang/go/issues/24355
从这位研发老铁的回复来看,意思就是:哥知道有这个bug,但是哥也不知道咋改。。。如果你只改了C文件,那么在go build的时候,请加上-a选项~
所以,这个问题有以下两种解决方案:
- 使用go build -a强制重新编译
- 随便修改一下Go文件(加个空格什么的。。),触发重新编译
更多文章欢迎关注“鑫鑫点灯”专栏: https://blog.csdn.net/turkeycock
或关注飞久微信公众号:以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 精读《手写 SQL 编译器 - 性能优化之缓存》
- @vue/cli 项目编译重复命中缓存问题解析
- Gradle 4.5 正式版发布,改进编译缓存和性能
- 轻松学会HTTP缓存(强缓存,协商缓存)
- 常见面试题之缓存雪崩、缓存穿透、缓存击穿
- HTTP缓存 - 强缓存/协商缓存/浏览器刷新
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。