欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go 語言中程序編譯過程詳解

 更新時間:2024年05月31日 16:54:17   作者:栗箏i  
本文旨在深入探討Go語言的編譯機(jī)制和最新的模塊管理系統(tǒng)——Go Modules,通過詳細(xì)的示例和步驟,我們將演示從簡單的 “Hello World” 程序到使用第三方庫的更復(fù)雜項(xiàng)目的開發(fā)過程,感興趣的朋友跟隨小編一起看看吧

在當(dāng)今快速發(fā)展的軟件開發(fā)領(lǐng)域,Go 語言(又稱 Golang)已經(jīng)成為了開發(fā)高性能應(yīng)用程序的熱門選擇。由 Google 開發(fā)并在 2009 年公開發(fā)布,Go 語言因其簡潔的語法、出色的并發(fā)支持以及優(yōu)秀的性能而受到廣泛歡迎。盡管 Go 的語法相對簡單,但它的編譯過程和模塊管理系統(tǒng)可能會讓初學(xué)者感到有些困惑,特別是那些從動態(tài)語言背景轉(zhuǎn)來的開發(fā)者。

本文旨在深入探討 Go 語言的編譯機(jī)制和最新的模塊管理系統(tǒng)——Go Modules。通過詳細(xì)的示例和步驟,我們將演示從簡單的 “Hello World” 程序到使用第三方庫的更復(fù)雜項(xiàng)目的開發(fā)過程。我們將開始于基本的編譯命令,探索如何手動處理依賴,然后過渡到使用 Go Modules 管理依賴,這在現(xiàn)代 Go 項(xiàng)目開發(fā)中已成為標(biāo)準(zhǔn)實(shí)踐。

1、編譯和運(yùn)行 Go 程序的基礎(chǔ)

在上一篇我們實(shí)現(xiàn) HelloWorld 程序的過程中,我們在運(yùn)行 “helloworld” 程序之前,是輸入了一個 go build 命令的:

$go build main.go

對此,如果有使用 C/C++ 和 gcc 或 clang 的開發(fā)經(jīng)驗(yàn)的同學(xué)家就會發(fā)現(xiàn) Go 的編譯步驟與它們非常類似。都是在編譯成功后,生成一個二進(jìn)制可執(zhí)行文件。

在 Linux 系統(tǒng)、macOS 系統(tǒng)或 Windows 系統(tǒng)的 PowerShell 中,可以通過執(zhí)行以下 ls 命令來查看這個新生成的可執(zhí)行文件:

$ls
main*    main.go

可以看到,在上面顯示的文件里面有我們剛剛創(chuàng)建的、以 .go 為后綴的源代碼文件,還有剛生成的可執(zhí)行文件(Windows 系統(tǒng)下為 main.exe,其余系統(tǒng)下為 main)。

如果你主要使用的是像 Ruby、Python 或 JavaScript 這樣的動態(tài)語言,那么你可能不太習(xí)慣需要在運(yùn)行程序之前先進(jìn)行編譯的步驟。

Go 是編譯型語言,這意味著我們必須先編譯 Go 程序,才能將生成的可執(zhí)行文件交給其他人,在沒有安裝 Go 的環(huán)境中也能運(yùn)行這些程序。相對地,如果你提供給別人的是 .rb、.py.js 文件,他們就需要在自己的環(huán)境中安裝相應(yīng)的 Ruby、Python 或 JavaScript 解釋器來執(zhí)行這些動態(tài)語言的源代碼。

當(dāng)然,Go 也借鑒了動態(tài)語言的一些對開發(fā)者體驗(yàn)較好的特性,比如基于源碼文件的直接執(zhí)行,Go 提供了 run 命令可以直接運(yùn)行 Go 源碼文件,比如我們也可以使用下面命令直接基于 main.go 運(yùn)行:

$go run main.go
hello, world

不過像 go run 這類命令更多用于開發(fā)調(diào)試階段,真正的交付成果還是需要使用 go build 命令構(gòu)建的。

然而,在我們的生產(chǎn)環(huán)境中,編譯 Go 程序通常不像之前提到的基于單個 Go 源文件構(gòu)建像"hello, world"這樣的簡單示例那么直接。隨著項(xiàng)目接近真實(shí)的生產(chǎn)條件,它的規(guī)模會增大、涉及的協(xié)作人員會增多,同時項(xiàng)目的依賴及其版本也會變得更為復(fù)雜。

2、Go Modules 機(jī)制

2.1、復(fù)雜項(xiàng)目下 Go 程序的編譯

現(xiàn)在,我們將啟動一個名為"hellomod"的新項(xiàng)目,在這個項(xiàng)目中,我們會使用兩個第三方庫:zapfasthttp。這將使 go build 的構(gòu)建過程更具挑戰(zhàn)性。

如同我們之前的"helloworld"示例一樣,我們可以通過以下命令來創(chuàng)建“hellomod”項(xiàng)目:

$mkdir hellomod
$cd hellomod

接著,我們在"hellomod"下創(chuàng)建并編輯我們的示例源碼 main.go 文件:

package main
import (
  "github.com/valyala/fasthttp"
  "go.uber.org/zap"
)
var logger *zap.Logger
func init() {
  logger, _ = zap.NewProduction()
}
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
  logger.Info("hello, go module", zap.ByteString("uri", ctx.RequestURI()))
}
func main() {
  fasthttp.ListenAndServe(":8081", fastHTTPHandler)
}

這個示例中,我們創(chuàng)建了一個在 8081 端口上監(jiān)聽的 HTTP 服務(wù)。當(dāng)向該服務(wù)發(fā)起請求時,它會在終端的標(biāo)準(zhǔn)輸出上打印一段訪問日志???/p>

以看出,相比于“hello, world”示例,這個項(xiàng)目明顯更加復(fù)雜。但目前,我們不需要深入了解每行代碼的具體作用。只要應(yīng)該我們在這個稍微復(fù)雜的示例中使用了兩個第三方依賴庫:zapfasthttp。

接下來,讓我們嘗試使用編譯"hello, world"時的方法來編譯“hellomod”項(xiàng)目中的 main.go 源文件,看看 Go 編譯器會給出什么樣的輸出結(jié)果:

$go build main.go
main.go:4:3: no required module provides package github.com/valyala/fasthttp: go.mod file not found in current directory or any parent directory; see 'go help modules'
main.go:5:3: no required module provides package go.uber.org/zap: go.mod file not found in current directory or any parent directory; see 'go help modules'

從編譯器的輸出來看,go build 似乎在找一個名為 go.mod 的文件,來解決程序?qū)Φ谌桨囊蕾嚊Q策問題。

2.2、go mod

Go 1.11 版本推出 modules 機(jī)制,簡稱 mod,更加易于管理項(xiàng)目中所需要的模塊。模塊是存儲在文件樹中的 Go 包的集合,其根目錄中包含 go.mod 文件。 go.mod 文件定義了模塊的模塊路徑,它也是用于根目錄的導(dǎo)入路徑,以及它的依賴性要求。每個依賴性要求都被寫為模塊路徑和特定語義版本。

Go 1.11 開始,Go 允許在 $GOPATH/src 外的任何目錄下使用 go.mod 創(chuàng)建項(xiàng)目。在 $GOPATH/src 中,為了兼容性,Go 命令仍然在舊的 GOPATH 模式下運(yùn)行。從 Go 1.13 開始,go.mod模式將成為默認(rèn)模式。

2.3、go mod 示例

現(xiàn)在,我們將通過以下命令為“hellomod”示例程序創(chuàng)建一個 go.mod 文件:

go mod init github.com/lizhengi/hellomod
go: creating new go.mod: module github.com/lizhengi/hellomod
go: to add module requirements and sums:
	go mod tidy

Ps:注意模塊命名方式,如果你的項(xiàng)目要發(fā)布到 github,則命名為:github.com/<USERNAME>/<MODULE_NAME>

此時可以看到,go mod init 命令的執(zhí)行結(jié)果是在當(dāng)前目錄下生成了一個 go.mod 文件:

$cat go.mod
module github.com/lizhengi/hellomod
go 1.17

實(shí)際上,一個 module 是多個包的集合,這些包與 module 一起進(jìn)行版本控制、發(fā)布和分發(fā)。go.mod 文件所在的目錄被視為聲明的 module 的根目錄。此時的 go.mod 文件內(nèi)容相對簡單,首行是用來聲明 module 路徑(module path)的。Module 本質(zhì)上引入了命名空間的概念,這意味著 module 下每個包的導(dǎo)入路徑都由 module path 和包所在的子目錄名共同構(gòu)成。

例如,在 hellomod 下有一個子目錄 pkg/pkg1,那么 pkg1 中的包的導(dǎo)入路徑將是 github.com/lizhengi/hellomod/pkg/pkg1。此外,go.mod 文件的最后一行是 Go 版本指示符,表示該 module 是基于特定 Go 版版本的 module 語義編寫的。

此時,我們執(zhí)行一下構(gòu)建,Go 編譯器輸出結(jié)果是這樣的

$go build main.go
main.go:4:2: no required module provides package github.com/valyala/fasthttp; to add it:
  go get github.com/valyala/fasthttp
main.go:5:2: no required module provides package go.uber.org/zap; to add it:
  go get go.uber.org/zap

你會看到,Go 編譯器提示源碼依賴 fasthttp 和 zap 兩個第三方包,但是 go.mod 中沒有這兩個包的版本信息,我們需要按提示手工添加信息到 go.mod 中。

這個時候,除了按提示手動添加外,我們也可以使用 go mod tidy 命令,讓 Go 工具自動添加:

$go mod tidy                       
go: finding module for package go.uber.org/zap
go: finding module for package github.com/valyala/fasthttp
go: downloading github.com/valyala/fasthttp v1.54.0
go: downloading go.uber.org/zap v1.27.0
go: found github.com/valyala/fasthttp in github.com/valyala/fasthttp v1.54.0
go: found go.uber.org/zap in go.uber.org/zap v1.27.0
go: downloading go.uber.org/multierr v1.10.0
go: downloading github.com/stretchr/testify v1.8.1
go: downloading go.uber.org/goleak v1.3.0
go: downloading github.com/andybalholm/brotli v1.1.0
go: downloading github.com/klauspost/compress v1.17.7
go: downloading github.com/valyala/bytebufferpool v1.0.0
go: downloading gopkg.in/yaml.v3 v3.0.1
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/pmezard/go-difflib v1.0.0

Ps:超時的話換個代理即可

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

Go 工具不僅下載并添加了 hellomod 直接依賴的 zap 和 fasthttp 包的信息,還下載了這兩個包的相關(guān)依賴包。go mod tidy 執(zhí)行后,我們 go.mod 的最新內(nèi)容變成了這個樣子:

module github.com/bigwhite/hellomod
go 1.16
require (
  github.com/valyala/fasthttp v1.28.0
  go.uber.org/zap v1.18.1
)

此時,go.mod 文件已經(jīng)包含了 hellomod 直接依賴的包的信息。此外,在 hellomod 目錄下還出現(xiàn)了一個名為 go.sum 的文件,這個文件記錄了 hellomod 的直接依賴和間接依賴包的版本 hash 值,這用于校驗(yàn)本地包的真實(shí)性。在構(gòu)建過程中,如果本地依賴包的 hash 值與 go.sum 文件中的記錄不匹配,構(gòu)建會被拒絕。

有了 go.mod 以及 hellomod 依賴的包版本信息后,我們再來執(zhí)行構(gòu)建:

$go build main.go
go: downloading go.uber.org/zap v1.27.0
go: downloading github.com/valyala/fasthttp v1.54.0
go: downloading go.uber.org/multierr v1.10.0
go: downloading github.com/andybalholm/brotli v1.1.0
go: downloading github.com/klauspost/compress v1.17.7
go: downloading github.com/valyala/bytebufferpool v1.0.0
$ls
go.mod    go.sum    main*    main.go

這次我們成功構(gòu)建出了可執(zhí)行文件 main,運(yùn)行這個文件,新開一個終端窗口,在新窗口中使用 curl 命令訪問該 http 服務(wù):curl localhost:8081/foo/bar,我們就會看到服務(wù)端輸出如下日志:

$./main
{"level":"info","ts":1716950836.531074,"caller":"hellomod/main.go:15","msg":"hello, go module","uri":"/foo/bar"}

到此這篇關(guān)于Go 語言中程序是怎么編譯的?的文章就介紹到這了,更多相關(guān)Go程序編譯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go 語言中程序編譯過程詳解

    Go 語言中程序編譯過程詳解

    本文旨在深入探討Go語言的編譯機(jī)制和最新的模塊管理系統(tǒng)——Go Modules,通過詳細(xì)的示例和步驟,我們將演示從簡單的 “Hello World” 程序到使用第三方庫的更復(fù)雜項(xiàng)目的開發(fā)過程,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Go語言為什么不支持前綴自增運(yùn)算符原理解析

    Go語言為什么不支持前綴自增運(yùn)算符原理解析

    這篇文章主要為大家介紹了Go語言為什么不支持前綴自增運(yùn)算符原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • golang?sync.Cond同步機(jī)制運(yùn)用及實(shí)現(xiàn)

    golang?sync.Cond同步機(jī)制運(yùn)用及實(shí)現(xiàn)

    在?Go?里有專門為同步通信而生的?channel,所以較少看到?sync.Cond?的使用,不過它也是并發(fā)控制手段里的一種,今天我們就來認(rèn)識下它的相關(guān)實(shí)現(xiàn),加深對同步機(jī)制的運(yùn)用
    2023-09-09
  • golang中使用sync.Map的方法

    golang中使用sync.Map的方法

    這篇文章主要介紹了golang中使用sync.Map的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Golang設(shè)計模式中抽象工廠模式詳細(xì)講解

    Golang設(shè)計模式中抽象工廠模式詳細(xì)講解

    抽象工廠模式用于生成產(chǎn)品族的工廠,所生成的對象是有關(guān)聯(lián)的。如果抽象工廠退化成生成的對象無關(guān)聯(lián)則成為工廠函數(shù)模式。比如本例子中使用RDB和XML存儲訂單信息,抽象工廠分別能生成相關(guān)的主訂單信息和訂單詳情信息
    2023-01-01
  • Go語言七篇入門教程七GC垃圾回收三色標(biāo)記

    Go語言七篇入門教程七GC垃圾回收三色標(biāo)記

    這篇文章主要為大家介紹了Go語言教程關(guān)于GC垃圾回收三色標(biāo)記的示例詳解,本篇文章是Go語言七篇入門教程系列文章,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • Golang中使用errors返回調(diào)用堆棧信息

    Golang中使用errors返回調(diào)用堆棧信息

    這篇文章給大家介紹了Golang中如何使用errors返回調(diào)用堆棧信息,文章通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • go?mod?tidy報錯解決方法詳解

    go?mod?tidy報錯解決方法詳解

    這篇文章主要為大家介紹了go?mod?tidy報錯解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • golang配制高性能sql.DB的使用

    golang配制高性能sql.DB的使用

    本文主要講述SetMaxOpenConns(),?SetMaxIdleConns()?和?SetConnMaxLifetime()方法,?您可以使用它們來配置sql.DB的行為并改變其性能,感興趣的可以了解一下
    2021-12-12
  • go zero微服務(wù)框架logx日志組件剖析

    go zero微服務(wù)框架logx日志組件剖析

    這篇文章主要為大家介紹了go zero微服務(wù)框架logx日志組件剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評論