如何編寫Go代碼

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

目錄 [−]

  1. 程式碼群組織
    1. 工作區Workspace
    2. GOPATH 環境變數
    3. Package路徑
    4. 第一個 Go 程式
    5. 第一個Go庫
    6. Package name
  2. 測試
  3. 遠程 package
  4. 下一步
  5. 尋求協助

官方原文: How to Write Go Code,
根據最新官方文檔翻譯。翻譯參考wang_yb的如何寫 go 代碼 。
因為官方文檔有更新,我根據新版本的文檔重新進行了翻譯。

本文示範如何開發一個簡單的 go package, 以及 go tool 的使用方法,
即擷取(fetch), 編譯(build), 安裝(install) go package 的標準方法和命令.

go tool 需要你按照一定的標準來組織代碼. 請仔細閱讀本文.
它介紹了用來構建和運行 Go 程式的最簡單方法.

介紹本文的視頻參照: https://www.youtube.com/watch?v=XCsL89YtqCs。

程式碼群組織

工作區Workspace

go tool 是設計用來和公用倉庫的開原始碼一起工作的.
即使你不需要發布你的代碼, go tool 的工作模型也同樣適用於你.

Go 代碼必須儲存在 工作區 中, 工作區 就是一個特定的目錄結構, 根目錄下有如下3個目錄:

  • src 目錄: 存放 go 源碼檔案, 按 package 來組織 (一個 package 一個檔案夾)
  • pkg 目錄: 存放 package 對象
  • bin 目錄: 存放可執行檔命令command

go tool 編譯 src 下的檔案, 並將編譯好的二進位檔案分別放入 pkg 或者 bin 檔案夾中.
src 目錄可以包含多個 版本控制倉庫(比如 Git 或 Mercurial), 用來管理代碼的開發.

一個實際的工作區的目錄結構如下:

123456789101112131415161718
bin/    hello                          # command executable    outyet                         # command executablepkg/    linux_amd64/        github.com/golang/example/            stringutil.a           # package objectsrc/    github.com/golang/example/        .git/                      # Git repository metadatahello/    hello.go               # command sourceoutyet/    main.go                # command source    main_test.go           # test sourcestringutil/    reverse.go             # package source    reverse_test.go        # test source

這個工作區包含一個倉庫(example),由兩個命令組成(hellooutyet),以及一個庫(stringutil)。

一個典型的工作區可能包含很多源碼庫,這些源碼庫包含著N多的packagecommand。大部分的Go程式員會將他們的源碼和依賴放在一個單一的工作區中。

命令Command和庫libraries由各種source package編譯而來。我們稍後再介紹它。

GOPATH 環境變數

GOPATH 環境變數指向你的 工作區 的位置. 這是你開發 Go 代碼時唯一需要設定的環境變數.

開始開發時, 建立 工作區 的檔案夾, 並設定對應的 GOPATH 環境變數.
你的 工作區 可以是任意檔案夾, 本文中使用的路徑是 $HOME/work
注意 不要把 GOPATH 設定為 go 的安裝路徑. (另一種常用設定方式是設定GOPATH=$HOME)

12
$ mkdir $HOME/work$ export GOPATH=$HOME/work

為了方便編譯出的命令的執行, 將上面的 bin 目錄加入到 PATH:

1
$ export PATH=$PATH:$GOPATH/bin

想瞭解更多設定GOPATH 環境變數的知識,可以查看go help gopath

Package路徑

標準庫中的 package 只要使用短路徑即可, 比如 "fmt", "net/http"。
對於自己的 package, 必須選一個基本路徑以防止以後和標準庫, 或者其他第三方的庫產生衝突。
如果你的代碼儲存在某個代碼倉庫, 那麼就可以使用那個代碼倉庫的根目錄作為你的 package 的基本路徑。
比如, 你有個 github 的賬戶在 github.com/user, 就可以使用 github.com/user 作為你的基本路徑。

注意 在能夠正確編譯代碼之前, 你並不需要發布你的代碼到遠端代碼倉庫。
但是如果有一天你發布代碼的話, 組織好你的代碼是個好習慣。
實際上, 你可以使用任意的路徑名稱, 只要它在 go 標準庫和龐大的 go 生態系統中是唯一的。
我們使用 "github.com/user" 作為基本路徑, 然後在工作區中建立檔案夾來儲存代碼:

1
$ mkdir -p $GOPATH/src/github.com/user

第一個 Go 程式

為了編譯和運行一個簡單的 GO 程式, 首先要確定 package 路徑(這裡使用 github.com/user/hello),
並且在工作區中建立對應 package 檔案夾.

1
$ mkdir $GOPATH/src/github.com/user/hello

下一步, 在上面檔案夾中建立 hello.go 檔案, 檔案內容如下:

1234567
package mainimport "fmt"func main() {fmt.Printf("Hello, world.\n")}

然後, 可以通過 go tool 來編譯和安裝上面的 hello 程式。

1
$ go install github.com/user/hello

注意 你可以在任何路徑下運行上述命令, go tool 會根據 GOPATH 環境變數來從工作區中尋找 github.com/user/hello。
如果在 package 所在檔案夾中運行 go install, 也可以省略 package 路徑。

12
$ cd $GOPATH/src/github.com/user/hello$ go install

上面的命令編譯了 hello 命令, 併產生此命令的二進位可執行檔。
然後將二進位檔案 hello 安裝到了 工作區 的 bin 檔案夾下(Windows 下是 hello.exe)
在我們的例子中, 就是 $GOPATH/bin/hello, 即 $HOME/work/bin/hello。

go tool 只有在出錯時才會輸出資訊, 如果上面的 go 命令沒有輸出就說明執行成功了.
然後, 就可以在命令列中運行這個命令了.

12
$ $GOPATH/bin/helloHello, world.

或者, 如果你將 $GOPATH/bin 加入到 PATH 中了的話, 也可以執行執行 hello 命令。

1
$ hello

如果你使用了代碼版本管理工具, 正好可以初始化你的倉庫, 添加檔案, 並 commit 你的第一個改變。
當然這個步驟是可選的, 寫 go 代碼並不強制要求使用代碼版本管理工具。

12345678
$ cd $GOPATH/src/github.com/user/hello$ git initInitialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/$ git add hello.go$ git commit -m "initial commit"[master (root-commit) 0b4507d] initial commit 1 file changed, 1 insertion(+)  create mode 100644 hello.go

你可以把發布這個倉庫作為練習題。

第一個Go庫

讓我們來寫一個庫, 並將之用於上面的 hello 程式中.
同樣, 首先確定 package 路徑 (這裡使用 github.com/user/stringutil), 並建立對應的檔案夾。

1
$ mkdir $GOPATH/src/github.com/user/stringutil

接著, 建立檔案 reverse.go, 內容如下:

1234567891011
// Package stringutil contains utility functions for working with strings.package stringutil// Reverse returns its argument string reversed rune-wise left to right.func Reverse(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)}

用 go build 來編譯此 package:

1
$ go build github.com/user/stringutil

或者在 package 的目錄下, 直接運行 go build

1
$ go build

上面的命令不會產生輸出檔案。 為了產生輸出檔案, 必須使用 go install 命令, 它會在 pkg 檔案夾下產生 package 對象.
stringutil package 編譯成功之後, 修改之前的 hello.go 檔案:

1234567891011
package mainimport ("fmt""github.com/user/stringutil")func main() {fmt.Printf(stringutil.Reverse("!oG ,olleH"))}

無論用 go tool 安裝 package 對象還是 二進位檔案, 它都會安裝所有的依賴.
所以當你安裝 hello 程式時,

1
$ go install github.com/user/hello

stringutil package 也會被自動安裝.

運行新的 hello 程式, 可以看到如下輸出:

12
$ helloHello, Go!

經過上面的步驟, 你的 工作區應該像下面這樣:

123456789101112
bin/    hello                 # command executablepkg/    linux_amd64/          # this will reflect your OS and architecture        github.com/user/            stringutil.a  # package objectsrc/    github.com/user/        hello/            hello.go      # command source        stringutil/            reverse.go    # package source

注意 go install 將 stringutil.a 放進了 pkg/linux_amd64 檔案夾下與源碼對應的目錄中。
以後, go tool 就可以找到這個 package, 從而判斷是否需要重新編譯。
linux_amd64 是表示當前使用的系統, 它的目的是為了區分交叉編譯出的其他平台的 package。

Go 編譯出的二進位檔案都是靜態連結的, 所以上面的 bin/hello 在執行時並不需要 linux_amd64/go-files/stringutil.a 檔案。

Package name

go 代碼檔案的第一行必須是:

1
package name

這裡的 name 作為 package 的預設名稱, 讓其他 package import 的時候用.(同個 package 中的所有檔案必須使用相同的 name)。
Go 約定 package name 是 import path 中最後一部分。
也就是說, 如果一個 package 被引用時寫成 "crypto/rot13", 那麼這個 package 的 name 就是 rot13。

編譯為可執行檔的代碼的 package name 必須是 main。

串連進同一個二進位檔案的package name 不一定要唯一, 只要 pakage 的 import path 是唯一的就行。
也就是上面的 crypto/rot13 必須唯一, 但是可以有 another-crypto/rot13。

Go 的命名規則可以參考: [Effective Go](http://golang.org/doc/effective_go.html#names)

測試

Go 中包含一個輕量級的測試架構, 由 go test 命令和 testing package 組成。

測試檔案的名稱以 _test.go 結尾, 其中包含格式如 func TestXXXX(t *testing.T)的函數。
測試架構會執行每個這樣的函數, 如果函數中調用了 t.Error 或者 t.Fail, 就認為測試失敗。

給上面的 package stringutil 增加測試檔案, 路徑: $GOPATH/src/github.com/user/stringutil/reverse_test.go , 內容如下:

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

運行測試的方法如下:

12
$ go test github.com/user/stringutilok  github.com/user/stringutil 0.165s

或者進入到 package stringutil 的目錄中後, 直接運行:

12
$ go testok  github.com/user/stringutil 0.165s

通過 go help test 或者 http://golang.org/pkg/testing/ 來進一步 GO 的測試架構。

遠程 package

Go 的 import path 指示如何從版本管理系統(Git 或者 Mercurial) 中擷取 package 的源碼。go tool 可以利用這個特性來自動擷取遠程倉庫的代碼。
比如, 下面的例子中使用的代碼同時也儲存在 github 上(http://github.com/golang/example)。
如果你在代碼中 import 了上面這個遠端 package, 那麼 go get 命令會自動 擷取, 編譯, 安裝這個 package。

123
$ go get github.com/golang/example/hello$ $GOPATH/bin/helloHello, Go examples!

如果工作區中沒有指定的 package,go get 命令會把這個 package 下載到 GOPATH 中定義的第一個工作區中。
(如果這個package已經存在,go get會跳過擷取這一步,執行go install相同的行為)

上面的 go get 命令執行之後, 檔案夾結構大致如下:

12345678910111213141516171819202122
bin/    hello                           # command executablepkg/    linux_amd64/        github.com/golang/example/            stringutil.a            # package object        github.com/user/            stringutil.a            # package objectsrc/    github.com/golang/example/.git/                       # Git repository metadata        hello/            hello.go                # command source        stringutil/            reverse.go              # package source            reverse_test.go         # test source    github.com/user/        hello/            hello.go                # command source        stringutil/            reverse.go              # package source            reverse_test.go         # test source

github.com 上的 hello 程式依賴同一個倉庫中的 package stringutil,
即 github.com 上的 hello.go 中引用了 github.com 上的 package stringutil, 所以, go get 命令也下載, 編譯, 安裝了 stringutil 模組。

1
import "github.com/golang/example/stringutil"

這個特性可以讓你的 go package 很容易的被別人使用.
Go Wiki 和 godoc.org 上列出了很多第三方 Go 工程。
關於使用 go tool 來使用遠程倉庫的更多資訊, 請參考: go help importpath

下一步

  • 訂閱 golang-announce 郵件清單來瞭解最新的 Go release 資訊
  • 將 Effective Go 作為參考資料來編寫整潔, 地道的 Go 代碼
  • 通過 A Tour of Go 來完成一次 go 的旅行
  • 訪問 documentation page 來瞭解一系列關於Go語言的有深度的文章, 以及 Go 庫和工具.

尋求協助

  • 尋求即時協助, 可以使用 FreeNode 的IRC server #go-nuts
  • Go 語言官方郵件清單 Go Nuts
  • 彙報 Go 語言的 bug 請使用 Go issue tracker
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.