How to Write GO Code 中文版

來源:互聯網
上載者:User
- 說明- [官方原文](https://golang.org/doc/code.html)- 本文按個人理解進行直譯,水平有限,難免有錯或偏差,歡迎批評指正- 在Go的官方文檔中,經常使用命令(command)這個詞來指代可執行程式,如命令列應用程式,這個會讓我們新手在閱讀文檔時感到困惑。所以,需要記住,在Go語言中,命令(command)是指任何可執行程式。作為對比,包(package)更常用來指語義上可匯入的功能單元- [Introduction](#1)- [Code Organization](#2)- [overview](#2.1)- [workspace](#2.2)- [the GOPATH environment variable](#2.3)- [import paths](#2.4)- [your first program](#2.5)- [your first library](#2.6)- [package names](#2.7)- [Testing](#3)- [remote packages](#4)- [what`s next](#5)- [getting help](#6)<h2 id='1'> introduction </h2>- 本文檔主要示範一個簡單 go 包的開發過程和對 go tool 的介紹,以及擷取,構建和安裝go包和命令的標準方式- Go tool 要求使用指定的方法組織代碼。- 如果可以翻牆看YouTube的話,有個[示範視頻](https://www.youtube.com/watch?v=XCsL89YtqCs)可以看<h2 id='2'> Code Organization </h2><h3 id='2.1'> overview </h3>- 通常來說Go開發人員將他所有的原始碼放到一個單個的工作空間(***workspace***)中- 一個工作空間中包含多個由比如Git這樣的版本控制系統的進行控制的倉庫(或者說資料庫)(***repositories***)- 每個倉庫包含一個或者多個包(***package***)- 每個包在一個單獨的目錄中,該目錄下包含一個或者多個GO原始碼檔案- 到包的目錄的路徑決定了它的匯入路徑(***import path***)需要注意,上面這個特點,與其他語言編程環境中每一個項目都放在一個分開的單獨工作空間並且每個工作空間都幾乎綁定到一個版本控制系統控制的倉庫,是不同的,(比如 node 的項目是可以放在不同的目錄中的,而不必將所有 node 的項目都放到一個工作空間的目錄下)<h3 id='2.2'> workspaces </h3>一個工作空間是一個階層目錄,在其根目錄包含以下三個目錄- src 包含Go語言的原始碼檔案- pkg 包含包對象- bin 包含可執行程式go tool 構建原始碼並將產生的二進位檔案放到 pkg 和 bin 目錄中。src 子目錄通常包含多個由比如Git或者Mercurial這樣的版本控制系統控制的倉庫來追蹤一個或者多個源包的開發過程。下面是個實際中的關於工作空間的簡要例子:```gobin/ 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 golang.org/x/image/ .git/ # Git repository metadatabmp/ reader.go # package source writer.go # package source ... (many more repositories and packages omitted) ...```上面的結構樹展示了一個工作空間包含兩個倉庫(example和image)。example庫包含兩個可執行程式(hello和outyet)和一個庫(stringutil)。image倉庫包含bmp包和幾個其他包一個典型的工作空間包含多個原始碼倉庫,每個倉庫包含許多包和可執行程式。絕大多數的go開發人員將他們的原始碼和依賴都放到一個工作空間中。可執行程式和庫(***libraries***) 是從不同的源碼包構建而來。<h3 id='2.3'> the GOPATH environment variable </h3>GOPATH 環境變數指明了工作空間的位置。它預設是在你的主目錄中的一個名為go的目錄, 所以在Unix下就是```$HOME/go```, 在Plan9下就是```$home/go```, 在Windows下就是```%USERPROFILE%/go```(通常是```C:\Users\YourName\go```).如果想在一個不同的目錄下工作,需要 [設定 GOPATH](https://github.com/golang/go/wiki/SettingGOPATH) 到想指定的目錄.(另一個通常的設定是設定 ```GOPATH=$HOME```).<strong>需要注意的是 GOPATH 和 go的安裝路徑不能相同</strong>.```go env GOPATH```命令列印出當前正在起效的GOPATH,如果GOPATH還沒有被設定,那就列印出預設位置(即上面預設的GOPATH的值)為了方便,添加工作空間的 bin 子目錄到path:```$ export PATH=$PATH:$(go env GOPATH)/bin```為了簡短一點,上面指令碼在本文末使用 ```$GOPATH``` 替換 ```$(go env GOPATH)```.要學習更多關於GOPATH環境變數相關的資訊,查看 [go help gopath](https://golang.org/cmd/go/#hdr-GOPATH_environment_variable)要使用通用工作空間位置,查看[設定GOPATH 環境變數](https://github.com/golang/go/wiki/SettingGOPATH)<h3 id='2.4'> import paths </h3>一個匯入路徑 ***import path*** 是唯一性地標誌一個包的字串。一個包的匯入路徑對應它在工作空間或者一個遠程倉庫中的位置(下面解釋).標準庫(standard library)中的包通常都給出一個比如 "fmt"或者"net/http"這樣簡短的import path. 對於你自己的包,需要選一個不會跟未來被添加到標準庫或者其他拓展庫的命名衝突的基礎路徑(base path)。我們選擇 github.com/user 作為我們的基礎路徑。在工作空間中建立一個目錄來存放原始碼:```$ mkdir -p $GOPATH/src/github.com/user```<h3 id='2.5'> your first program </h3>為了編譯和運行一個簡單的程式,首先選一個包路徑(我們將使用 github.com/user/hello)然後在工作目錄中建立一個對應的包目錄```$mkdir $GOPATH/src/github.com/user/hello```然後,在那個目錄裡面建立一個命名為hello.go的檔案,並把下面的代碼放上去:```gopackage mainimport "fmt"func main(){fmt.Printf("Hello, world.\n")}```現在,可以使用go tool 來 構建(***build***) 並且安裝上面的程式了:```$ go install github.com/user/hello```你可以在你系統的任何地方運行上面的命令. go tool 會根據 GOPATH 指明的工作空間到 github.com/user/hello 包中找到原始碼.如果從包目錄中運行 go install,你可以忽略掉包的路徑:```$cd $GOPATH/src/github.com/user/hello$go install```上面的命令將會構建 hello 命令,產生一個可執行二進位檔案。然後將二進位檔案以hello命名(在 Windows下是 hello.exe)安裝到工作空間的 bin 目錄下。在我們的例子中就是 ```$GOPATH/bin/hello```, 也就是 ```$HOME/go/bin/hello```.go tool 只有在產生錯誤時才列印輸出,所以如果上面的命令執行之後沒有產生任何列印輸出,那就是執行成功了。現在可以通過全路徑運行命令: ```$ $GOPATH/bin/helloHello, world```或者也可以添加 ```$GOPATH/bin```到你的 PATH,然後運行二進位檔案就可以執行命令了:```$ helloHello, world```如果你在使用原始碼控制系統,現在可以初始化一個倉庫,添加檔案,然後提交第一次的更改了。這一步是可選的```$ 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```<h3 id='2.6'> your first library </h3>選擇一個包路徑(在這我們將使用 github.com/user/stringutil)然後建立一個包目錄來寫一個庫並使用:```$ mkdir $GOPATH/src/github.com/user/stringutil```接著在上面目錄中建立一個名為 reverse.go 的檔案並放上下面的內容:```go// 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 來編譯上面建立的包:```$ go build github.com/user/stringutil```或者, 如果你是在上面的包的目錄下的話,直接運行下面的命令:```$ go build```上面的命令不會產生一個檔案。如果想要產生檔案,必須使用 go install,這樣的話會在工作空間的 pkg 的目錄中產生一個包對象。確認 stringutil 包被構建之後,更改hello.go(在```$GOPATH/src/github.com/user/hello```目錄下)來使用它```gopackage mainimport ("fmt""github.com/user/stringutil")func main() {fmt.Printf(stringutil.Reverse("!oG ,olleH"))}```任何時候 go tool 安裝了一個包或者二進位檔案, 包或者二進位檔案裡面的所有依賴也會被安裝,所以當安裝 hello 程式, stringutil 包也同時會自動被安裝```$go install github.com/user/hello```執行新版本的程式,應該可以看到一個新的資訊```$ hello Hello, Go!```上面所有的步驟執行完之後,工作空間看起來應該是下面這樣的:```gobin/ 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 可以找到包對象並避免對包進行不必要的重編譯。linux_amd64可以協助交叉編譯,並反映作業系統和系統的結構。Go 命令可執行檔是靜態連結的:運行 Go 程式不需要包對象的存在<h3 id='2.7'> package names </h3>Go 源檔案的第一條語句必須是:```gopackage name```***name*** 是包的匯入預設名字(其他檔案匯入這個包時使用的名稱)(一個包中的所有檔案都必須是相同的***name***)包名作為匯入路徑的最後一個元素是Go的慣例。如果被匯入的包是```cryto/rot13```那麼包應該被命名為 ```rot13```。可執行程式必須使用總是使用 package main。被連結到一個單個二進位檔案的所有包,這些包的名稱不要求名字唯一性,只要包的匯入路徑(包的完整的檔案名稱)是唯一的即可查看 [Effective Go](https://golang.org/doc/effective_go.html#names) 來瞭解更多關於包的命名慣例資訊<h2 id='3'> Testing </h2>Go 有一個由 go test 命令和 testing 包組成的輕量級的測試架構.建立一個以 _test.go為檔案名稱尾碼的檔案,檔案中包含名為 TestXXX 的簽名 func (t *testing.T)的函數,通過這樣的方式來編寫測試。測試架構運行每一個這樣的函數,如果函數調用類似 t.Error 或者 t.Fail 的報錯函數,那麼說明這裡面對應的測試案例已經失敗.建立 ```$GOPATH/src/github.com/user/stringutil/reverse_test.go```檔案,把下面的代碼放上去,這樣就為 stringutil包添加了測試.```gopackage 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)}}}```運行下面的命令來跑測試:```$ go test github.com/user/stringutilok github.com/user/stringutil 0.165s //這是運行命令的結果```另外,如果你是在包的目錄下的話,不用跑上面的命令,直接跑下面的命令即可```$ go testok github.com/user/stringutil 0.165s //這是運行命令的結果```運行 [go helo test](https://golang.org/cmd/go/#hdr-Test_packages) 以及查看 [testing package documentation](https://golang.org/pkg/testing/)來瞭解更多資訊<h2 id='4'> remote packages </h2>一個匯入路徑可以描述如何通過使用比如git或者marcurial這樣的版本控制系統來擷取包的原始碼。go tool 使用這個特性來自動從遠處倉庫擷取包。舉個栗子,在這個文檔中描述的例子同時是一個託管在 github.com/golang/example 的Git倉庫。如果在包的匯入路徑中包含這個倉庫的URL,那麼, go get 會自動地擷取,構建,然後安裝它:```$ go get github/com/golang/example/hello$ $GOPATH/bin/helloHello, Go examples?```如果指定的包沒有出現在工作空間中,go get 將會把該指定的包放置通過GOPATH指定的第一個工作空間中。(如果該包早已經存在將要被放置的工作空間中,go get 將會跳過從遠程倉庫擷取的過程從而繼續執行go install)執行完上面 go get 命令之後,工作空間的分類樹看起來應該是下面這樣的:```gobin/ 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上託管的hello命令依賴於同一個存放庫中的stringutil包. hello.go 檔案中的匯入使用相同的匯入路徑約定,因此 go get 也可以找到並安裝依賴的包。```goimport "github.com/golang/example/stringutil"```這個約定是讓你的go 包可以被其他go開發人員使用的最簡單的方法。[Go wiki](https://github.com/golang/go/wiki/Projects)和[godoc.org](https://godoc.org/)提供裡go的拓展項目.想要瞭解更多的關於使用 go tool 來擷取遠程倉庫的資訊,查看[go help importpath](https://golang.org/cmd/go/#hdr-Remote_import_paths)<h2 id='5'> what`s next </h2>看一下 [Effective Go](https://golang.org/doc/effective_go.html)看一下 [A Tour of Go](https://tour.golang.org/welcome/1)看一下 [documentation page](https://golang.org/doc/#articles)<h2 id='6'> getting help </h2>如果需要即時協助,訪問[Freenode](http://freenode.net/)官方關於go的探討的郵件清單在[Go Nuts](https://groups.google.com/forum/#!forum/golang-nuts)有bug想上報?到[Go issue tracker](https://github.com/golang/go/issues)311 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.