Go1.10 中的 go build
引入了缓存机制,导致 gocode
完全不能使用(gocode#500),bug 报了好几个,但作者表示目前太忙没有时间修复。
Matthew Dempsky 的 fork 使用源码解析的方式解决了问题,但性能太差,不论项目大小,每次都要好几秒才能给出自动完成提示。他的另一个分支,尝试从编译缓存中提取信息来提高性能,但前提是包必须被编译过,我试了一下,感觉不好用。
但没自动提示写代码太费劲了,遂决定自己动手,丰衣足食。先是找到了这篇文档,读了一遍觉得太复杂,短时间内啃不动,就再找投机取巧的方法,发现源码解析的主要逻辑都在 go/internal/srcimporter
这,而这个包代码量不大,细读之后更发现它已经使用了缓存,只不过这个缓存绑到了 importer 实例上,不同实例不能共享。所以,基于 srcimporter
的代码,把缓存提升到全局级别即可。
代码放到了 https://github.com/localvar/gocode,需要的请自取。自己随便测了测,没发现大问题,第一次自动提示时由于缓存是空的,会比较慢,后面缓存建立起来了就好多了。
本来想着建个 PR 把改动提交给 Matthew Dempsky,但觉得我的改法只是个临时方案(srcimporter
是内部包,但我把它的代码复制了一份出来修改,如果 Go1.11 有什么变动,这个方案就又废了),故放弃。
已知问题:
- 不支持
Cgo
,原始的srcimporter
就不支持,所以这个不是我的错。 - 每个自动提示请求中都有个
context
,其中包含了当前使用的GOOS
,GOARCH
等信息,context
不同,源码的解析结果就可能有差别。使用全局包缓存后,会出现缓存的包是基于context A
建立的而请求要求使用context B
的情况,这可能导致一些错误。不过,我觉得context
切换的频率应该不高,所以问题不严重。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于