如何編寫Go代碼


非常重要的兩個地址

介紹

本文檔演示了在模塊內開發一個簡單的 Go 包,並介紹了  go tool:這是獲取、構建和安裝 Go 模塊、包和命令的標准方法。

注意: 本文假定你使用的是Go 1.13或更高版本的Go,並且GO111MODULE環境變量沒有設置。如果你要找這個文檔的舊版本、前模塊的版本,here.。

代碼組織形式
Go程序被組織成。一個包是同一目錄下的源文件的集合,這些源文件被編譯在一起。在一個源文件中定義的函數、類型、變量和常量對同一包內的所有其他源文件都是可見的。

一個存儲庫包含一個或多個模塊。一個模塊是由一起發布的相關的Go包組成的集合。一個 Go 倉庫通常只包含一個模塊,位於倉庫的根目錄下。

一個名為go.mod的文件在那里聲明了模塊路徑:模塊內所有包的導入路徑前綴。該模塊包含了包含go.mod文件的目錄中的包,以及該目錄的子目錄,直到下一個包含go.mod文件的子目錄(如果有的話)。

注意,你不需要先把代碼發布到遠程倉庫中,然后才構建它。一個模塊可以在本地定義,而不屬於一個版本庫。然而,像這樣組織你的代碼是一個好習慣,就像你有一天會發布代碼一樣。

每個模塊的路徑不僅可以作為它的包的導入路徑前綴,還可以指示go命令應該在哪里下載它。例如,為了下載golang.org/x/tools模塊,go命令將查詢https://golang.org/x/tools(這里有更多描述here)。

導入路徑是一個用於導入包的字符串。一個包的導入路徑是指它的模塊路徑和模塊內的子目錄。例如,模塊github.com/google/go-cmp目錄中包含了一個包,在cmp/目錄下。這個包的導入路徑是github.com/google/go-cmp/cmp。標准庫中的包沒有模塊路徑前綴。

你的第一個程序
要編譯和運行一個簡單的程序,首先選擇一個模塊路徑(我們將使用 example.com/user/hello),然后創建一個 go.mod 文件並聲明它。命令如下

 

$ mkdir hello # Alternatively, clone it if it already exists in version control.
$ cd hello
$ go mod init example.com/user/hello
go: creating new go.mod: module example.com/user/hello
$ cat go.mod
module example.com/user/hello

go 1.14
$

 

Go源文件中的第一個語句必須是package name。可執行的命令必須始終使用package main

接下來,在該目錄下創建一個名為hello.go的文件,包含以下Go代碼。

 

package main

import "fmt"

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

現在你可以用go工具建立並安裝該程序。

$ go install example.com/user/hello
$

這個命令建立hello命令,生成一個可執行的二進制文件。然后,它將這個二進制文件安裝到 $HOME/go/bin/hello (或者在 Windows 下,%USERPROFILE%go\bin\hello.exe)。

安裝目錄由GOPATH和GOBIN環境變量控制。如果設置了GOBIN,二進制文件就會被安裝到這個目錄下。如果設置了GOPATH,二進制文件將被安裝到GOPATH列表中第一個目錄的bin子目錄。否則,二進制文件會被安裝到默認的GOPATH目錄下的bin子目錄($HOME/go或%USERPROFILE/go)。

你可以使用 go env 命令來為未來的 go 命令設置環境變量的默認值。

$ go env -w GOBIN=/somewhere/else/bin
$
要取消之前通過go env -w設置的變量,請使用go env -u。

$ go env -u GOBIN
$
像go install這樣的命令適用於包含當前工作目錄的模塊的上下文。如果工作目錄不在 example.com/user/hello 模塊中,go 安裝可能會失敗。

為了方便起見,go命令接受相對於工作目錄的路徑,如果沒有給出其他路徑,則默認為當前工作目錄下的包。所以在我們的工作目錄下,以下命令都是等價的。

$ go install example.com/user/hello
$ go install .
$ go install

接下來,讓我們來運行程序,確保它能正常運行。為方便起見,我們將把安裝目錄添加到PATH中,以便於運行二進制文件。

# Windows users should consult https://github.com/golang/go/wiki/SettingGOPATH
# for setting %PATH%.
$ export PATH=$PATH:$(dirname $(go list -f '{{.Target}}' .))
$ hello
Hello, world.
$

如果你使用的是源碼控制系統,現在是初始化倉庫,添加文件,並提交第一次修改的好時機。同樣,這一步是可選的:如果你不使用源碼控制來編寫Go代碼。

$ git init
Initialized empty Git repository in /home/user/hello/.git/
$ git add go.mod hello.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 7 insertion(+)
 create mode 100644 go.mod hello.go
$

go命令通過請求相應的HTTPS URL和讀取HTML響應中的元數據來定位包含給定模塊路徑的存儲庫(參見go help importpath)。許多托管服務已經為包含Go代碼的資源庫提供了元數據,因此,要讓你的模塊供他人使用,最簡單的方法就是讓它的模塊路徑與資源庫的URL匹配。

從你的模塊中導入包
讓我們寫一個morestrings包,從hello程序中使用它。首先,為包創建一個目錄,命名為$HOME/hello/morestrings,然后在該目錄下創建一個名為reverse.go的文件,內容如下。

// Package morestrings implements additional functions to manipulate UTF-8
// encoded strings, beyond what is provided in the standard "strings" package.
package morestrings

// ReverseRunes returns its argument string reversed rune-wise left to right.
func ReverseRunes(s string) string {
    r := []rune(s)
    for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return string(r)
}

因為我們的ReverseRunes函數是以大寫字母開頭的,所以它是exported的,可以在其他import我們morestrings包的包中使用。

讓我們用go build來測試一下這個包的編譯。

$ cd $HOME/hello/morestrings
$ go build
$

這不會產生一個輸出文件。相反,它將編譯后的包保存在本地構建緩存中。

在確認了morestrings包的構建后,讓我們在hello程序中使用它。為此,修改你原來的 $HOME/hello/hello/hello.go 來使用 morestrings 包。

package main

import (
    "fmt"

    "example.com/user/hello/morestrings"
)

func main() {
    fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}

安裝hello程序。

$ go install example.com/user/hello

運行新版本的程序,你應該會看到一條新的、相反的消息。

$ hello
Hello, Go!

從遠程模塊導入包

一個導入路徑可以描述如何使用版本控制系統(如Git或Mercurial)獲取包的源代碼。go工具使用這個屬性來自動從遠程版本庫中獲取包。例如,在你的程序中使用github.com/google/go-cmp/cmp。

package main

import (
    "fmt"

    "example.com/user/hello/morestrings"
    "github.com/google/go-cmp/cmp"
)

func main() {
    fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
    fmt.Println(cmp.Diff("Hello World", "Hello Go"))
}

當你運行go install、go build或go run等命令時,go命令會自動下載遠程模塊並將其版本記錄在你的go.mod文件中。

$ go install example.com/user/hello
go: finding module for package github.com/google/go-cmp/cmp
go: downloading github.com/google/go-cmp v0.4.0
go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.4.0
$ hello
Hello, Go!
  string(
-     "Hello World",
+     "Hello Go",
  )
$ cat go.mod
module example.com/user/hello

go 1.14

require github.com/google/go-cmp v0.4.0
$

模塊的依賴關系會自動下載到GOPATH環境變量指示的目錄下的pkg/mod子目錄。給定版本的模塊的下載內容會在所有需要該版本的模塊中共享,所以go命令將這些文件和目錄標記為只讀。要刪除所有下載的模塊,你可以通過 -modcache 標志來清除。

$ go clean -modcache
$
測試
Go有一個由go test命令和testing包組成的輕量級測試框架。

你通過創建一個以_test.go命名的文件來編寫一個測試,該文件包含一個名為TestXXX的函數,簽名為func(t *testing.T)。測試框架會運行每個這樣的函數;如果函數調用了失敗函數,如t.Error或t.Fail,則認為測試失敗。

通過創建文件$HOME/hello/morestrings/reverse_test.go,在morestrings包中添加一個測試,其中包含以下Go代碼。

package morestrings

import "testing"

func TestReverseRunes(t *testing.T) {
    cases := []struct {
        in, want string
    }{
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    }
    for _, c := range cases {
        got := ReverseRunes(c.in)
        if got != c.want {
            t.Errorf("ReverseRunes(%q) == %q, want %q", c.in, got, c.want)
        }
    }
}

然后用go test運行測試。

$ go test
Passed
OK example.com/user/morestrings 0.165s
$
運行 go help test ,查看測試包文檔了解更多細節 testing package documentation.
接下來

訂閱  golang-announce 郵件列表,當 Go 的新穩定版本發布時,你會收到通知。

請參閱  Effective Go ,了解如何寫出清晰、流暢的 Go 代碼。

也可以從入門教程開始:https://tour.golang.org/ 還有中文版 https://tour.go-zh.org/

訪問documentation page,了解有關go語言及其庫和工具的深度文章。

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM