天天看點

go安裝編譯運作

安裝

語言環境

可參考: https://www.runoob.com/go/go-environment.html

安裝包下載下傳位址為:​​https://golang.org/dl/​​。

如果打不開可以使用這個位址:​​https://golang.google.cn/dl/​​。

驗證

go version      
go安裝編譯運作

內建環境

推薦:vscode , goLand

vscode安裝插件支援

go安裝編譯運作

hello,world

建立項目檔案夾,go-demo

mkdir go-demo
cd go-demo      

編寫第一個程式

Go 源檔案總是用全小寫字母形式的短小單詞命名,并且以.go 擴充名結尾

如果要在源檔案的名字中使用多個單詞,我們通常直接是将多個單詞連接配接起來作為源檔案名,而不是使用其他分隔符,比如下劃線。也就是說,我們通常使用 helloworld.go 作為檔案名而不是 hello_world.go。因為下劃線這種分隔符,在 Go 源檔案命名中有特殊作用!

touch main.go      
package main

import "fmt"

func main() {
    fmt.Println("hello, world")
}      

編譯,運作

go build ./main.go
./main      

示例代碼結構

定義了 Go 中的一個包 package。包是 Go 語言的基本組成單元,通常使用單個的小寫單詞命名,一個 Go 程式本質上就是一組包的集合。所有 Go 代碼都有自己隸屬的包,在這裡我們的“hello,world”示例的所有代碼都在一個名為 main 的包中。main 包在 Go 中是一個特殊的包,整個 Go 程式中僅允許存在一個名為 main 的包。

package main      

main 包中的主要代碼是一個名為 main 的函數:

func main() {

  fmt.Println("hello,world")

}

這裡的 main 函數會比較特殊:當你運作一個可執行的 Go 程式的時候,所有的代碼都會從這個入口函數開始運作。這段代碼的第一行聲明了一個名為 main 的、沒有任何參數和傳回值的函數。如果某天你需要給函數聲明參數的話,那麼就必須把它們放置在圓括号 () 中。

另外,那對花括号{}被用來标記函數體,Go 要求所有的函數體都要被花括号包裹起來。按照慣例,我們推薦把左花括号與函數聲明置于同一行并以空格分隔。

main 函數體中之是以可以調用 fmt 包的 Println 函數,還有最後一個原因,那就是 Println 函數名的首字母是大寫的。在 Go 語言中,隻有首字母為大寫的辨別符才是導出的(Exported),才能對包外的代碼可見;如果首字母是小寫的,那麼就說明這個辨別符僅限于在聲明它的包内可見。

在 Go 語言中,main 包是不可以像标準庫 fmt 包那樣被導入(Import)的,如果導入 main 包,在代碼編譯階段你會收到一個 Go 編譯器錯誤:import “xx/main” is a program, not an importable package。

我們傳入的字元串也就是我們執行程式後在終端的标準輸出上看到的字元串。這種“所見即所得”得益于 Go 源碼檔案本身采用的是 Unicode 字元集,而且用的是 UTF-8 标準的字元編碼方式,這與編譯後的程式所運作的環境所使用的字元集和字元編碼方式是一緻的。

Go 語言的正式文法規範是使用分号“;”來做結尾辨別符的。那為什麼我們很少在 Go 代碼中使用和看到分号呢?這是因為,大多數分号都是可選的,常常被省略,不過在源碼編譯時,Go 編譯器會自動插入這些被省略的分号。加上分号也是完全合法的,是可以直接通過 Go 編譯器編譯并正常運作的。不過,gofmt 在按約定格式化代碼時,會自動删除這些被我們手工加入的分号的。

自動格式化 fmt

Go 語言内置了一套 Go 社群約定俗稱的代碼風格,并随安裝包提供了一個名為 Gofmt 的工具,這個工具可以幫助你将代碼自動格式化為約定的風格。

Gofmt 是 Go 語言在解決規模化(scale)問題上的一個最佳實踐,并成為了 Go 語言吸引其他語言開發者的一大賣點。很多其他主流語言也在效仿 Go 語言推出自己的 format 工具,比如:Java formatter、Clang formatter、Dartfmt 等。是以,作為 Go 開發人員,請在送出你的代碼前使用 Gofmt 格式化你的 Go 源碼。

go fmt ./main.go      

編譯

Go 是一種編譯型語言,這意味着隻有你編譯完 Go 程式之後,才可以将生成的可執行檔案傳遞于其他人,并運作在沒有安裝 Go 的環境中。

go build

go build main.go      

go run

Go 也借鑒了動态語言的一些對開發者體驗較好的特性,比如基于源碼檔案的直接執行,Go 提供了 run 指令可以直接運作 Go 源碼檔案,比如我們也可以使用下面指令直接基于 main.go 運作:

go run main.go      

像 go run 這類指令更多用于開發調試階段,真正的傳遞成果還是需要使用 go build 指令建構的。

複雜項目下 Go 程式的編譯

越貼近真實的生産環境,也就意味着項目規模越大、協同人員越多,項目的依賴和依賴的版本都會變得複雜。

mkdir hellomodule
cd hellomodule
touch 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)
}      

go module 

Go module 構模組化式是在 Go 1.11 版本正式引入的,為的是徹底解決 Go 項目複雜版本依賴的問題,在 Go 1.16 版本中,Go module 已經成為了 Go 預設的包依賴管理機制和 Go 源碼建構機制。生成 go.mod 檔案。

Go Module 的核心是一個名為 go.mod 的檔案,在這個檔案中存儲了這個 module 對第三方依賴的全部資訊。

接下來,我們就通過下面指令為“hello,module”這個示例程式添加 go.mod 檔案:

go mod init github.com/wanghaokun/go-demo/hellomodule      

go mod init 指令的執行結果是在目前目錄下生成了一個 go.mod 檔案,

用于聲明 module 路徑(module path)的。而且,module 隐含了一個命名空間的概念,module 下每個包的導入路徑都是由 module path 和包所在子目錄的名字結合在一起構成。

go 1.18 是一個 Go 版本訓示符,用于表示這個 module 是在某個特定的 Go 版本的 module 語義的基礎上編寫的。

一個 module 就是一個包的集合,這些包和 module 一起打版本、釋出和分發。go.mod 所在的目錄被我們稱為它聲明的 module 的根目錄。

go mod tidy

使用 go mod tidy 指令,讓 Go 工具 自動添加源碼依賴 fasthttp 和 zap 兩個第三方包

go mod tidy      

國内運作,可能在存在引入第三方包時,出現加載逾時的情況

修改為國内源位址
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/      

go.mod 已經記錄了 hellomodule 直接依賴的包的資訊。不僅如此,hellomodule 目錄下還多了一個名為 go.sum 的檔案,這個檔案記錄了 hellomodule 的直接依賴和間接依賴包的相關版本的 hash 值,用來校驗本地包的真實性。在建構的時候,如果本地依賴包的 hash 值與 go.sum 檔案中記錄的不一緻,就會被拒絕建構。

有了 go.mod 以及 hellomodule 依賴的包版本資訊後,我們再來執行建構:

go build main.go
./main      

新起一個視窗,通路

curl localhost:8080/foo/bar      

檢視go輸出

總結

  1. Go 包是 Go 語言的基本組成單元。一個 Go 程式就是一組包的集合,所有 Go 代碼都位于包中;
  2. Go 源碼可以導入其他 Go 包,并使用其中的導出文法元素,包括類型、變量、函數、方法等,而且,main 函數是整個 Go 應用的入口函數;
  3. Go 源碼需要先編譯,再分發和運作。如果是單 Go 源檔案的情況,我們可以直接使用 go build 指令 +Go 源檔案名的方式編譯。不過,對于複雜的 Go 項目,我們需要在 Go Module 的幫助下完成項目的建構。