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

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

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

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

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

1、編譯和運行 Go 程序的基礎

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

$go build main.go

對此,如果有使用 C/C++ 和 gcc 或 clang 的開發(fā)經驗的同學家就會發(fā)現(xiàn) Go 的編譯步驟與它們非常類似。都是在編譯成功后,生成一個二進制可執(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)語言,那么你可能不太習慣需要在運行程序之前先進行編譯的步驟。

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

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

$go run main.go
hello, world

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

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

2、Go Modules 機制

2.1、復雜項目下 Go 程序的編譯

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

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

$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 服務。當向該服務發(fā)起請求時,它會在終端的標準輸出上打印一段訪問日志。可

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

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

$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 的文件,來解決程序對第三方包的依賴決策問題。

2.2、go mod

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

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

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:注意模塊命名方式,如果你的項目要發(fā)布到 github,則命名為:github.com/<USERNAME>/<MODULE_NAME>

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

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

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

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

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

$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 包的信息,還下載了這兩個包的相關依賴包。go mod tidy 執(zhí)行后,我們 go.mod 的最新內容變成了這個樣子:

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 文件已經包含了 hellomod 直接依賴的包的信息。此外,在 hellomod 目錄下還出現(xiàn)了一個名為 go.sum 的文件,這個文件記錄了 hellomod 的直接依賴和間接依賴包的版本 hash 值,這用于校驗本地包的真實性。在構建過程中,如果本地依賴包的 hash 值與 go.sum 文件中的記錄不匹配,構建會被拒絕。

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

$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

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

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

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

相關文章

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

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

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

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

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

    golang?sync.Cond同步機制運用及實現(xiàn)

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

    golang中使用sync.Map的方法

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

    Golang設計模式中抽象工廠模式詳細講解

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

    Go語言七篇入門教程七GC垃圾回收三色標記

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

    Golang中使用errors返回調用堆棧信息

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

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

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

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

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

    go zero微服務框架logx日志組件剖析

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

最新評論