最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go中的交叉編譯問題

 更新時間:2023年11月22日 14:49:38   作者:機器鈴砍菜刀  
這篇文章主要介紹了Go中的交叉編譯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

交叉編譯是指在一個硬件平臺生成另一個硬件平臺的可執(zhí)行文件。而Go提供了非常方便的交叉編譯方式。

如何編譯

Go交叉編譯,涉及到幾個環(huán)境變量的設(shè)置: GOARCH、GOOS和CGO_ENABLED。

  • GOARCH:編譯目標(biāo)平臺的硬件體系架構(gòu)(amd64, 386, arm, ppc64等)。
  • GOOS:編譯目標(biāo)平臺上的操作系統(tǒng)(darwin, freebsd, linux, windows)。
  • CGO_ENABLED:代表是否開啟CGO,1表示開啟,0表示禁用。由于CGO不能支持交叉編譯,所以需要禁用。

GO中env的具體環(huán)境變量的注釋,可通過輸入命令go help environment查看。

 ~ $ go help environment
...
  GOARCH
    The architecture, or processor, for which to compile code.
    Examples are amd64, 386, arm, ppc64.
...
  GOOS
    The operating system for which to compile code.
    Examples are linux, darwin, windows, netbsd.
...
  CGO_ENABLED
    Whether the cgo command is supported. Either 0 or 1.

Mac 下編譯 Linux 和 Windows 64位可執(zhí)行程序

export CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
export CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

Linux 下編譯 Mac 和 Windows 64位可執(zhí)行程序

export CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
export CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

Windows 下編譯 Mac 和 Linux 64位可執(zhí)行程序

SET CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
SET CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

其他平臺或32位系統(tǒng)類似,這里就不再贅述。

GO是如何做到交叉編譯?

Go交叉編譯的實現(xiàn)通過在文件頂部增加構(gòu)建標(biāo)記,進行選擇編譯。

// +build

注:Go源碼里的編譯器源碼位于$GOROOT/src/cmd/compile路徑下,鏈接器源碼位于$GOROOT/src/link路徑下。

我們的切入點從Go編譯器的main函數(shù)為入口,代碼位于$GOROOT/src/cmd/compile/main.go。

以環(huán)境變量GOARCH為例,看一下Go編譯器是如何通過構(gòu)建標(biāo)記來選擇對應(yīng)的體系架構(gòu)目標(biāo)進行編譯。

package main
?
// 引用了Go所能支持的所有架構(gòu)體系庫代碼,根據(jù)GOARCH選擇對應(yīng)的體系代碼
import (  
  "cmd/compile/internal/amd64"
  "cmd/compile/internal/arm"
  "cmd/compile/internal/arm64"
 ....
  "cmd/compile/internal/x86"
...
)
?
// 初始化代碼
var archInits = map[string]func(*gc.Arch){
  "386":      x86.Init,
  "amd64":    amd64.Init,
  "arm":      arm.Init,
  "arm64":    arm64.Init,
...
}
?
func main() {
  // disable timestamps for reproducible output
  log.SetFlags(0)
  log.SetPrefix("compile: ")
?
// 通過objabi.GOARCH選擇對應(yīng)的架構(gòu)體系
  archInit, ok := archInits[objabi.GOARCH]
...
  gc.Main(archInit)
...
}

objabi.GOARCH是$GOROOT/src/cmd/internal/objabi/util.go中的變量GOARCH。

var (
  defaultGOROOT string // set by linker
?
...
  GOROOT   = envOr("GOROOT", defaultGOROOT)
  GOARCH   = envOr("GOARCH", defaultGOARCH)
  GOOS     = envOr("GOOS", defaultGOOS)
...
)

defaultGOARCH是runtime包里的GOARCH值,如下所示。

// Code generated by go tool dist; DO NOT EDIT.
?
package objabi
?
import "runtime"
?
...
const defaultGOOS = runtime.GOOS
const defaultGOARCH = runtime.GOARCH
...

而該值又是通過sys.GOARCH賦值。$GOROOT/src/runtime/extern.go。

// GOARCH is the running program's architecture target:
// one of 386, amd64, arm, s390x, and so on.
const GOARCH string = sys.GOARCH

終于來到了重點!$GOROOT/src/runtime/internal/sys/agoarch_amd64.go

// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.
?
// 我的機器平臺是amd64,且未對GOARCH的值做修改。因此這里的構(gòu)建標(biāo)簽是amd64.
// +build amd64
?
package sys
?
const GOARCH = `amd64`

通過構(gòu)建amd64的編譯標(biāo)簽,從而控制了Go編譯時需要選擇對應(yīng)的架構(gòu)代碼。即:如果不是amd64,例如arm,那對應(yīng)的編譯代碼就是$GOROOT/src/runtime/internal/sys/agoarch_arm.go。

如何利用交叉編譯?

雖然golang 可以跨平臺編譯,但卻無法解決系統(tǒng)的差異性。在靠近底層邏輯的項目中,我們需要直接調(diào)用操作系統(tǒng)函數(shù),例如同樣是實現(xiàn)IO多路服用,在darwin系統(tǒng)調(diào)用kqueue,而linux系統(tǒng)需調(diào)用epoll。

相同功能可以編寫類似xxx_windows.go xxx.Linux.go文件,根據(jù)操作系統(tǒng)編譯對應(yīng)源文件,而不是在文件中用if else規(guī)劃執(zhí)行路徑。

交叉編譯同樣可以理解為條件編譯,通過構(gòu)建的build標(biāo)簽,選擇需要編譯進最終執(zhí)行二進制文件的代碼。

這里給一個簡單的條件編譯示例,如下。

代碼文件

  • go.mod
  • main.go
  • myfunc.go

main.go:程序入口,調(diào)用位于myfunc.go中的speak函數(shù)。

package main
?
import "fmt"
?
func main() {
  fmt.Println("mike")
  speak("hello")
}

myfunc.go: 構(gòu)建了build標(biāo)簽,需要build命令 帶上-tag speak,該代碼才能被編譯。

//+build speak
?
package main
?
func speak(s string) {
  println("speak:", s)
}

執(zhí)行命令

$ go build -o main
$ ./main

輸出

mike

可以看到,在main函數(shù)中的speak()函數(shù)并沒有被執(zhí)行,因為myfunc.go沒有被編譯。

如果需要將myfunc.go編譯進最終的執(zhí)行代碼,則執(zhí)行命令

$ go build -tags speak -o main
$ ./main

輸出

$ mike
$ speak: hello

上述條件編譯示例對你是否有啟發(fā)呢?

舉例:

項目開發(fā)中,如果想打印程序中的某些信息以便調(diào)試,而又不想打印相關(guān)代碼生成到最終的可執(zhí)行文件中,那么條件編譯便可派上用場。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • golang實現(xiàn)nacos獲取配置和服務(wù)注冊-支持集群詳解

    golang實現(xiàn)nacos獲取配置和服務(wù)注冊-支持集群詳解

    文章介紹了如何在Go語言中使用Nacos獲取配置和服務(wù)注冊,支持集群初始化,客戶端結(jié)構(gòu)體中的IpAddresses可以配置多個地址,新客戶端支持集群配置,文章還討論了如何將Nacos獲取到的配置與項目中的Viper無縫對接,以便進行Viper的正常操作
    2025-11-11
  • Golang的命名規(guī)范及最佳實踐(推薦!)

    Golang的命名規(guī)范及最佳實踐(推薦!)

    這篇文章主要給大家介紹了關(guān)于Golang的命名規(guī)范及最佳實踐的相關(guān)資料,命名規(guī)則涉及變量、常量、全局函數(shù)、結(jié)構(gòu)、接口、方法等的命名,文中介紹的非常詳細,需要的朋友可以參考下
    2023-10-10
  • PHP結(jié)構(gòu)型模式之組合模式

    PHP結(jié)構(gòu)型模式之組合模式

    這篇文章主要介紹了PHP組合模式Composite Pattern優(yōu)點與實現(xiàn),組合模式是一種結(jié)構(gòu)型模式,它允許你將對象組合成樹形結(jié)構(gòu)來表示“部分-整體”的層次關(guān)系。組合能讓客戶端以一致的方式處理個別對象和對象組合
    2023-04-04
  • Golang繼承模擬實例詳解

    Golang繼承模擬實例詳解

    這篇文章主要介紹了Golang繼承模擬方法,結(jié)合實例形式分析了Go語言實現(xiàn)繼承的原理與相關(guān)操作技巧,需要的朋友可以參考下
    2016-07-07
  • Go語言TCP從原理到代碼實現(xiàn)詳解

    Go語言TCP從原理到代碼實現(xiàn)詳解

    這篇文章主要為大家介紹了Go語言TCP從原理到代碼實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 8種超簡單的Golang生成隨機字符串方式分享

    8種超簡單的Golang生成隨機字符串方式分享

    這篇文章主要為大家詳細介紹了8種超簡單的Golang生成隨機字符串方式,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie

    go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie

    這篇文章主要介紹了go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie,文章圍繞主題展開詳細內(nèi)容介紹,具有一定得參考價值,需要的小伙伴可以參考一下
    2022-05-05
  • 淺析go中的map數(shù)據(jù)結(jié)構(gòu)字典

    淺析go中的map數(shù)據(jù)結(jié)構(gòu)字典

    golang中的map是一種數(shù)據(jù)類型,將鍵與值綁定到一起,底層是用哈希表實現(xiàn)的,可以快速的通過鍵找到對應(yīng)的值。這篇文章主要介紹了go中的數(shù)據(jù)結(jié)構(gòu)字典-map,需要的朋友可以參考下
    2019-11-11
  • 詳解Go語言中如何創(chuàng)建Cron定時任務(wù)

    詳解Go語言中如何創(chuàng)建Cron定時任務(wù)

    Cron是一個強大的定時任務(wù)調(diào)度庫,它允許開發(fā)者在Go應(yīng)用中方便地設(shè)置和管理定時任務(wù),本文將結(jié)合具體案例,詳細介紹Cron在Go語言中的用法,需要的可以參考下
    2024-10-10
  • Go語言中g(shù)oroutine的使用

    Go語言中g(shù)oroutine的使用

    本文主要介紹了Go語言中g(shù)oroutine的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06

最新評論

漳浦县| 阿拉善左旗| 盘山县| 淳化县| 丹东市| 武冈市| 铅山县| 林州市| 舞阳县| 临江市| 定兴县| 丹东市| 永仁县| 嘉禾县| 嘉荫县| 泰州市| 喀喇沁旗| 明星| 天全县| 青阳县| 土默特左旗| 恩施市| 绥中县| 贵定县| 万年县| 哈密市| 竹溪县| 海淀区| 瑞安市| 右玉县| 喀喇沁旗| 加查县| 东阳市| 增城市| 福海县| 高唐县| 儋州市| 温泉县| 西平县| 澄江县| 平陆县|