大家好,我是煎鱼。
成都创新互联主打移动网站、成都网站建设、成都网站制作、网站改版、网络推广、网站维护、主机域名、等互联网信息服务,为各行业提供服务。在技术实力的保障下,我们为客户承诺稳定,放心的服务,根据网站的内容与功能再决定采用什么样的设计。最后,要实现符合网站需求的内容、功能与设计,我们还会规划稳定安全的技术方案做保障。
最近因为各种奇怪的原因,接触到了 Go 特色之一 CGO。这方面的相关内容也相对少一些,给大家抛砖引玉。
图片来源于 marlin
毕竟很多跨语言调用,还是会依赖 CGO 这个特性。希望大家在真正要用时有个前置知识垫肚子。
CGO 就是 C 和 Go,两个编程语言。指的是能够创建调用 C 代码的 Go 包。对照着 Go 代码中的 “C”:
package main
import "C"
func main() {}
一旦程序中出现 import "C",则意味着开启 CGO 特性。在进行 go build 等阶段时,将会调用 C 编译器(通常是 gcc 或 clang)。
CGO 对应的环境变量是 CGO_ENABLED,设置为 1 则开启 CGO,为 0 则关闭 CGO。
编译命令如下:
CGO_ENABLED=0 go build -o hellojy main.go
当然,对于默认值。该环境变量值为 1,C 编译器也是使用 gcc。我们可以通过 go env 看到:
一旦关闭就会影响 CGO 编译。需要特别留意,交叉编译时会默认关闭 CGO。
先来一个 CGO 的 Go 例子:
package main
//#include
import "C"
func main() {
s := C.CString("hello world.")
C.puts(s)
}
运行 go run main.go,输出结果:
hello world.
如果你没有了解过 CGO,看到上面的例子,可能会有好几个疑问。
首先是 include:
//#include
import "C"
import "C" 我们懂,是导入 C 的伪包。前面的注解是什么?
无论是:
//#include
又或是:
/*
#include
#include
*/
实际上这是导入 C 前的注解,注解内容可以包含任何 C 代码,例如:函数、变量的声明定义、库引用等。(该注解要紧挨导入语句)
回到 Demo 本身,如果我们去掉 //#include
# command-line-arguments
./main.go:7:2: could not determine kind of name for C.puts
去掉后,语句 C.puts(s) 将无法运行。
实际上 stdio.h 的全称是:standard input output.header(标准输入输出头文件)。该文件大都是些输入输出函数的声明,引用了这库,就能使用 C 的 puts 方法。
其他同理,你在注解中声明、定义的东西,均可以在 Go 代码中通过 C 这个伪包来引用和调用。
其次像是 CString 方法,属于在 Go 和 C 类型之间需要复制数据的特殊函数,伪包 C 有进行预定义。
例如:
func C.CString(string) *C.char
func C.CBytes([]byte) unsafe.Pointer
func C.GoString(*C.char) string
func C.GoStringN(*C.char, C.int) string
func C.GoBytes(unsafe.Pointer, C.int) []byte
Go 官方有提供一份基础类型的对照表,大家可以参照来使用和理解。
如下:
C 语言类型 |
CGO 类型 |
Go语言类型 |
char |
C.char |
byte |
singed char |
C.schar |
int8 |
unsigned char |
C.uchar |
uint8 |
short |
C.short |
int16 |
unsigned short |
C.ushort |
uint16 |
int |
C.int |
int32 |
unsigned int |
C.uint |
uint32 |
long |
C.long |
int32 |
unsigned long |
C.ulong |
uint32 |
long long int |
C.longlong |
int64 |
unsigned long long int |
C.ulonglong |
uint64 |
float |
C.float |
float32 |
double |
C.double |
float64 |
size_t |
C.size_t |
uint |
使用 CGO,除了会带来一定的性能损耗外。需要特别注意的是:内存泄露。因为 Go 是带垃圾回收机制的编程语言,而使用了 C 后,需要手动的管理内存。
还是这个 Demo:
package main
//#include
import "C"
func main() {
s := C.CString("hello world.")
C.puts(s)
}
如果这是一个常驻进程,也没有任何释放动作。用 C.CString 方法所申请的变量 s 就会泄露。
因此与 “C” 相关的变量创建,需要进行手动的内存管理。正确的代码如下:
/*
#include
#include
*/
import "C"
import (
"unsafe"
)
func main() {
b := C.CString("hello world.")
C.puts(b)
C.free(unsafe.Pointer(b))
}
需要调用 C.free 方法进行主动的内存释放。如果该程序自然结束,也会自动回收。
在今天这篇文章中,我们介绍了 Go 语言中 CGO 的基础知识和快速入门。整体上,只要适应了写法,CGO 的用法就不算太麻烦。
需要特别注意手动内存管理、性能损耗等多方面的制约。后续我们也会继续深入 CGO 方面的内容。
网页标题:快速上手GoCGO,掌握在Go里写C!
转载来源:http://www.gawzjz.com/qtweb2/news18/1518.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联