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

Go語言中程序是怎么編譯的實現(xiàn)

 更新時間:2024年06月27日 08:33:08   作者:栗箏i  
本文主要介紹了Go語言中程序是怎么編譯的實現(xiàn),深入探討Go語言的編譯機制和最新的模塊管理系統(tǒng)Go Modules的使用,具有一定的參考價值,感興趣的可以了解一下

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

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

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

$go build main.go

對此,如果有使用 C/C++ 和 gcc 或 clang 的開發(fā)經(jīng)驗的同學(xué)家就會發(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)語言,那么你可能不太習(xí)慣需要在運行程序之前先進行編譯的步驟。

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

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

$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"這樣的簡單示例那么直接。隨著項目接近真實的生產(chǎn)條件,它的規(guī)模會增大、涉及的協(xié)作人員會增多,同時項目的依賴及其版本也會變得更為復(fù)雜。

2、Go Modules 機制

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

現(xiàn)在,我們將啟動一個名為"hellomod"的新項目,在這個項目中,我們會使用兩個第三方庫:zap 和 fasthttp。這將使 go build 的構(gòu)建過程更具挑戰(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 服務(wù)。當(dāng)向該服務(wù)發(fā)起請求時,它會在終端的標(biāo)準(zhǔn)輸出上打印一段訪問日志???/p>

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

接下來,讓我們嘗試使用編譯"hello, world"時的方法來編譯“hellomod”項目中的 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 機制,簡稱 mod,更加易于管理項目中所需要的模塊。模塊是存儲在文件樹中的 Go 包的集合,其根目錄中包含 go.mod 文件。 go.mod 文件定義了模塊的模塊路徑,它也是用于根目錄的導(dǎo)入路徑,以及它的依賴性要求。每個依賴性要求都被寫為模塊路徑和特定語義版本。

從 Go 1.11 開始,Go 允許在 $GOPATH/src 外的任何目錄下使用 go.mod 創(chuàng)建項目。在 $GOPATH/src 中,為了兼容性,Go 命令仍然在舊的 GOPATH 模式下運行。從 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:注意模塊命名方式,如果你的項目要發(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

實際上,一個 module 是多個包的集合,這些包與 module 一起進行版本控制、發(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 值,這用于校驗本地包的真實性。在構(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,運行這個文件,新開一個終端窗口,在新窗口中使用 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語言中程序是怎么編譯的實現(xiàn)的文章就介紹到這了,更多相關(guān)Go語言編譯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang實現(xiàn)java uuid的序列化方法

    golang實現(xiàn)java uuid的序列化方法

    這篇文章主要介紹了golang實現(xiàn)java uuid的序列化方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Go語言實現(xiàn)一個Http?Server框架(一)?http庫的使用

    Go語言實現(xiàn)一個Http?Server框架(一)?http庫的使用

    本文主要介紹用Go語言實現(xiàn)一個Http?Server框架中對http庫的基本使用說明,文中有詳細(xì)的代碼示例,感興趣的同學(xué)可以借鑒一下
    2023-04-04
  • golang?recover函數(shù)使用中的一些坑解析

    golang?recover函數(shù)使用中的一些坑解析

    這篇文章主要為大家介紹了golang?recover函數(shù)使用中的一些坑解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • Golang Gob編碼(gob包的使用詳解)

    Golang Gob編碼(gob包的使用詳解)

    這篇文章主要介紹了Golang Gob編碼(gob包的使用詳解),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 基于context.Context的Golang?loader緩存請求放大問題解決

    基于context.Context的Golang?loader緩存請求放大問題解決

    這篇文章主要為大家介紹了基于context.Context的Golang?loader緩存請求放大解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • golang簡易實現(xiàn)?k8s?的yaml上傳并應(yīng)用示例方案

    golang簡易實現(xiàn)?k8s?的yaml上傳并應(yīng)用示例方案

    這篇文章主要為大家介紹了golang簡易實現(xiàn)?k8s?的yaml上傳并應(yīng)用示例方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • Go雪花算法的作用領(lǐng)域及實現(xiàn)方法示例

    Go雪花算法的作用領(lǐng)域及實現(xiàn)方法示例

    這篇文章主要為大家介紹了Go雪花算法的作用領(lǐng)域及實現(xiàn)方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • golang gin 監(jiān)聽rabbitmq隊列無限消費的案例代碼

    golang gin 監(jiān)聽rabbitmq隊列無限消費的案例代碼

    這篇文章主要介紹了golang gin 監(jiān)聽rabbitmq隊列無限消費,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • Go語言中切片使用的注意事項小結(jié)

    Go語言中切片使用的注意事項小結(jié)

    切片是引用類型,相信對大家來說都不陌生,下面這篇文章主要給大家總結(jié)介紹了關(guān)于Go語言中切片使用的一些注意事項,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • 詳解Go語言如何解決map并發(fā)安全問題

    詳解Go語言如何解決map并發(fā)安全問題

    常說go語言是一門并發(fā)友好的語言,對于并發(fā)操作總會在編譯期完成安全檢查,所以這篇文章我們就來聊聊go語言是如何解決map這個數(shù)據(jù)結(jié)構(gòu)的線程安全問題吧
    2024-04-04

最新評論