cgo简介
什么是cgo
在某些场景下go很可能需要调动c函数,比如调用系统底层驱动。c在过去几十年的积累了非常多优秀的lib库,所以很多编程语言都会选择跨语言调用c,这项技术被称为foreign-function interfaces (简称ffi)。go和c语言有相当深的颜渊,go当然不会拒绝继承c语言的这些财产,于是便有了cgo。
cgo是golang自带的go和c互相调用的工具。注意go不仅仅可以调用c,而且还可以让c调用go。
cgo is not go
任何技术都不是完美的,虽然go可以通过cgo的方式使用c语言的很多优秀的lib库,但是cgo的使用并不是没有代价的,在某些场景下代价还挺大。cgo is not go这个文章详细描述了cgo不是很让人满意的地方。
总的来说有如下几点:
- cgo让构建go程序变得复杂,必须安装c语言相关工具链
- cgo不支持交叉编译
- cgo无法使用go语言很多工具,像pprof
- 用了cgo后部署变得更加复杂。c语言很多依赖动态链接库,go语言原先只编成一个二进制可执行文件,现在这种局面被打破。
- cgo代理额外的性能损耗。cgo中go的堆栈和c语言堆栈是分开的,go调用c语言函数通常需要申请额外的堆内存进行数据拷贝。
cgo作用大,但是非必要条件不要使用cgo。
cgo hello world
package main
/*
#include <stdio.h>
#include <stdlib.h> //C.free 依赖这个头文件
void myprint(char* s) {
printf("%s\n", s);
}
*/
import "C"
import "unsafe"
func main() {
cs := C.CString("Hello from stdio\n")
C.myprint(cs)
C.free(unsafe.Pointer(cs))
}
$ go run main.go
Hello from stdio