cgo了解过引入的风险点吗?

题目来源:新浪

答案1:

几个方面。1内存管理。Go采用垃圾回收机制,而C采用手工内存管理。开发人员在GC与“记着释放内存”的规则间切换,极易产生bug。

2.函数多返回值。Go支持多返回值,而C并不支持,因此当将C函数用在多返回值的Go调用中时,C的errno将作为函数返回值列表中最后那个error返回值返回。

3.goroutine与C线程阻塞导致线程数增多。goroutine和内核线程之间通过多路复用方式对应,这样通常Go应用会启动很多goroutine,但创建的线程数量是有限的。Go优化了一些原本会导致线程阻塞的系统调用,通过运行时调度在不创建新线程的情况下依旧能达到同样的效果。但是Go调度器无法掌控C。如果cgo调用的C代码有线程阻塞情况,这时Go运行时调度代码只能创建新的线程以供其他没有绑定M的P上的goroutine使用。这会使得Go应用进程内线程数量暴涨的可能性大增,这与Go承诺的轻量级并发有背离。

4.失去跨平台交叉构建能力。Go本身有很不错的可移植性。Go还为Gopher提供了主流编程语言中最好的跨平台交叉编译能力。但这种跨平台编译能力仅限于纯Go代码。如果我们跨平台编译使用了cgo技术的Go源文件,会出现意想不到错误。默认情况下,cgo模式默认关闭。在macOS上,即便显式开启cgo,cgo调用的macOS上的外部链接器clang也会因无法识别目标平台的目标文件格式而报错,macOS上的clang默认并不具备跨平台编译Linux应用的能力。

5.性能开销问题。在性能方面,C代码之于Go就好比汇编代码之于C。但是如果语言之间互调次数过多,反而会增大调用开销。比如在Go循环中使用cgo。因此,尽量将代码下推到C中以减少语言间交互调用的次数。