自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

快速上手 Go CGO,掌握在 Go 里寫 C!

開發(fā) 前端
在今天這篇文章中,我們介紹了 Go 語言中 CGO 的基礎(chǔ)知識和快速入門。整體上,只要適應(yīng)了寫法,CGO 的用法就不算太麻煩。

大家好,我是煎魚。

最近因為各種奇怪的原因,接觸到了 Go 特色之一 CGO。這方面的相關(guān)內(nèi)容也相對少一些,給大家拋磚引玉。

圖片

圖片來源于 marlin

畢竟很多跨語言調(diào)用,還是會依賴 CGO 這個特性。希望大家在真正要用時有個前置知識墊肚子。

CGO 是什么

CGO 就是 C 和 Go,兩個編程語言。指的是能夠創(chuàng)建調(diào)用 C 代碼的 Go 包。對照著 Go 代碼中的 “C”:

package main

import "C"

func main() {}

一旦程序中出現(xiàn) import "C",則意味著開啟 CGO 特性。在進行 go build 等階段時,將會調(diào)用 C 編譯器(通常是 gcc 或 clang)。

CGO 對應(yīng)的環(huán)境變量是 CGO_ENABLED,設(shè)置為 1 則開啟 CGO,為 0 則關(guān)閉 CGO。

編譯命令如下:

CGO_ENABLED=0 go build -o hellojy main.go

當然,對于默認值。該環(huán)境變量值為 1,C 編譯器也是使用 gcc。我們可以通過 go env 看到:

圖片

一旦關(guān)閉就會影響 CGO 編譯。需要特別留意,交叉編譯時會默認關(guān)閉 CGO。

CGO 快速上手

最小 Demo

先來一個 CGO 的 Go 例子:

package main

//#include <stdio.h>
import "C"

func main() {
 s := C.CString("hello world.")
 C.puts(s)
}

運行 go run main.go,輸出結(jié)果:

hello world.

聲明 C 注解

如果你沒有了解過 CGO,看到上面的例子,可能會有好幾個疑問。

首先是 include:

//#include <stdio.h>
import "C"

import "C" 我們懂,是導入 C 的偽包。前面的注解是什么?

無論是:

//#include <stdio.h>

又或是:

/*
#include <stdio.h>
#include <stdlib.h>
*/

實際上這是導入 C 前的注解,注解內(nèi)容可以包含任何 C 代碼,例如:函數(shù)、變量的聲明定義、庫引用等。(該注解要緊挨導入語句)

回到 Demo 本身,如果我們?nèi)サ?nbsp;//#include <stdio.h>,再運行會出現(xiàn)如下報錯:

# 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(標準輸入輸出頭文件)。該文件大都是些輸入輸出函數(shù)的聲明,引用了這庫,就能使用 C 的 puts 方法。

其他同理,你在注解中聲明、定義的東西,均可以在 Go 代碼中通過 C 這個偽包來引用和調(diào)用。

其次像是 CString 方法,屬于在 Go 和 C 類型之間需要復制數(shù)據(jù)的特殊函數(shù),偽包 C 有進行預(yù)定義。

例如:

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 類型對照

Go 官方有提供一份基礎(chǔ)類型的對照表,大家可以參照來使用和理解。

如下:

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,除了會帶來一定的性能損耗外。需要特別注意的是:內(nèi)存泄露。因為 Go 是帶垃圾回收機制的編程語言,而使用了 C 后,需要手動的管理內(nèi)存。

還是這個 Demo:

package main

//#include <stdio.h>
import "C"

func main() {
 s := C.CString("hello world.")
 C.puts(s)
}

如果這是一個常駐進程,也沒有任何釋放動作。用 C.CString 方法所申請的變量 s 就會泄露。

因此與 “C” 相關(guān)的變量創(chuàng)建,需要進行手動的內(nèi)存管理。正確的代碼如下:

/*
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
 "unsafe"
)

func main() {
 b := C.CString("hello world.")
 C.puts(b)
 C.free(unsafe.Pointer(b))
}

需要調(diào)用 C.free 方法進行主動的內(nèi)存釋放。如果該程序自然結(jié)束,也會自動回收。

總結(jié)

在今天這篇文章中,我們介紹了 Go 語言中 CGO 的基礎(chǔ)知識和快速入門。整體上,只要適應(yīng)了寫法,CGO 的用法就不算太麻煩。

需要特別注意手動內(nèi)存管理、性能損耗等多方面的制約。后續(xù)我們也會繼續(xù)深入 CGO 方面的內(nèi)容。

責任編輯:武曉燕 來源: 腦子進煎魚了
相關(guān)推薦

2022-08-23 08:53:31

Go項目語言

2023-09-26 01:21:34

2021-02-02 09:10:12

Go語言二進制

2021-02-05 18:22:51

GoC剖析

2022-12-07 09:00:18

錯誤異常CGO

2022-12-01 08:15:41

CGOswitcherror

2021-09-29 18:17:30

Go泛型語言

2023-03-27 09:40:01

GoWebAssembl集成

2022-03-25 21:57:49

匯編Go語言

2024-10-30 09:50:51

WebGo語言

2021-11-10 15:37:49

Go源碼指令

2021-03-10 08:55:42

Go數(shù)據(jù)語言

2025-02-10 08:49:40

2023-05-08 07:55:05

快速排序Go 語言

2023-03-29 08:18:16

Go調(diào)試工具

2023-12-01 08:01:33

GoValidator

2012-03-20 09:20:40

Go語言

2025-03-26 00:55:00

2021-08-13 11:45:00

Go語言字節(jié)

2024-04-11 07:40:55

Go并發(fā)編程
點贊
收藏

51CTO技術(shù)棧公眾號