Go有強烈的C背景,除了語法具有繼承性外,其設計者以及其設計目標都與C語言有着千絲萬縷的聯繫。在Go與C語言互操作(Interoperability)方面,Go更是提供了強大的支持。尤其是在Go中使用C,你甚至可以直接在Go源文件中編寫C代碼,這是其他語言所無法望其項背的。下面是小編爲大家帶來的Go與C語言的操作的知識,歡迎閱讀。
一、Go調用C代碼的原理
下面是一個短小的例子:
複製代碼
package main
// #include
// #include
/*
void print(char *str) {
printf("%s", str);
}
*/
import "C"
import "unsafe"
func main() {
s := "Hello Cgo"
cs := ing(s)
t(cs)
(ter(cs))
}
複製代碼
與"正常"Go代碼相比,上述代碼有幾處"特殊"的地方:
1) 在開頭的註釋中出現了C頭文件的include字樣
2) 在註釋中定義了C函數print
3) import的一個名爲C的"包"
4) 在main函數中居然調用了上述的那個C函數-print
沒錯,這就是在Go源碼中調用C代碼的步驟,可以看出我們可直接在Go源碼文件中編寫C代碼。
首先,Go源碼文件中的C代碼是需要用註釋包裹的,就像上面的include 頭文件以及print函數定義;
其次,import "C"這個語句是必須的,而且其與上面的C代碼之間不能用空行分隔,必須緊密相連。這裏的"C"不是包名,而是一種類似名字空間的概念,或可以理解爲僞包,C語言所有語法元素均在該僞包下面;
最後,訪問C語法元素時都要在其前面加上僞包前綴,比如和上面代碼中的t、等。
我們如何來編譯這個go源文件呢?其實與"正常"Go源文件沒啥區別,依舊可以直接通過go build或go run來編譯和執行。但實際編譯過程中,go調用了名爲cgo的工具,cgo會識別和讀取Go源文件中的C元素,並將其提取後交給C編譯器編譯,最後與Go源碼編譯後的目標文件鏈接成一個可執行程序。這樣我們就不難理解爲何Go源文件中的C代碼要用註釋包裹了,這些特殊的語法都是可以被Cgo識別並使用的。
二、在Go中使用C語言的類型
1、原生類型
* 數值類型
在Go中可以用如下方式訪問C原生的數值類型:
複製代碼
,
r (signed char),
r (unsigned char),
t,
rt (unsigned short),
, (unsigned int),
,
g (unsigned long),
long (long long),
glong (unsigned long long),
t,
le
複製代碼
Go的數值類型與C中的數值類型不是一一對應的。因此在使用對方類型變量時少不了顯式轉型操作,如Go doc中的這個例子:
複製代碼
func Random() int {
return int(om())// -> Go的int
}
func Seed(i int) {
dom((i))//Go的uint -> C的uint
}
複製代碼
* 指針類型
原生數值類型的'指針類型可按Go語法在類型前面加上*,比如var p *。而void*比較特殊,用Go中的ter表示。任何類型的指針值都可以轉換爲ter類型,而ter類型值也可以轉換爲任意類型的指針值。ter還可以與uintptr這個類型做相互轉換。由於ter的指針類型無法做算術操作,轉換爲uintptr後可進行算術操作。
* 字符串類型
C語言中並不存在正規的字符串類型,在C中用帶結尾'