C/C++经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化.Go语言必须能够站在C/C++这个巨人的肩膀之上,有了海量的C/C++软件资产兜底之后,我们才可以放心愉快地用Go语言编程.C语言作为一个通用语言,很多库会选择提供一个C兼容的API,然后用其他不同的编程语言实现.Go语言通过自带的一个叫CGO的工具来支持C语言函数调用,同时我们可以用Go语言导出C动态库接口给其它语言使用
cgo的价值
- 没有银弹, Go语言也不是银弹, 无法解决全部问题
- 通过CGO可以继承C/C++将近半个世纪的软件积累
- 通过CGO可以用Go给其它系统写C接口的共享库
- CGO是Go和其它语言直接通讯的桥梁
- CGO 是一个保底的后备技术
- CGO 是 Go 的替补技术
可能的cgo的场景
- 通过OpenGL或OpenCL使用显卡的计算能力
- 通过OpenCV来进行图像分析
- 通过Go编写Python扩展
- 通过Go编写移动应用
编写cgo程序
要使用cgo特性,需要事先安装c/c++构建工具链,例如Linux下的gcc,windows下的MinGW工具
如果在Go代码中出现了import “C”语句则表示使用了CGO特性,紧跟在这行语句前面的注释是一种特殊语法,里面包含的是正常的C语言代码.当确保CGO启用的情况下,还可以在当前目录中包含C/C++对应的源文件
示例:
1 | package main |
该示例展示了cgo的基本用法:开头的注释包括了需要调用的C函数和相关的头文件,头文件被include之后里面的所有的C语言元素都会被加入到”C”这个虚拟的包中(import “C”语句必须单独一行,不能和其他导入语句一起写)
向C函数传递参数也很简单,就直接转化成对应C语言类型传递就可以
cgo语句
在import “C”语句前的注释中可以通过#cgo语句设置编译阶段和链接阶段的相关参数
编译阶段的参数主要用于定义相关宏和指定头文件检索路径
链接阶段的参数主要是指定库文件检索路径和要链接的库文件
1 | // #cgo CFLAGS: -DPNG_DEBUG=1 -I./include |
CFLAGS部分,-D部分定义了宏PNG_DEBUG,值为1,-I定义了头文件包含的检索目录
LDFLAGS部分,-L指定了链接时库文件检索目录,-l指定了链接时需要链接png库
小结
cgo为C语言和Go语言提供了双向通讯的桥梁,个人认为学好cgo对自己的能力提升用处很大