開始編寫Golang代碼

介紹

本文主要講述如何寫一個簡單的Go包和如何使用golang的工具,如何獲取、編譯和安裝Go的包,以及如何使用go的命令。html

Go的工具須要將代碼按照必定的方式來組織。因此請認真閱讀本文。linux

代碼的組織

workspace

go工具是設計用來處理公開代碼庫的開源代碼的,雖然你不是必定要公開你的代碼,可是工做的模式是同樣的。git

Go代碼必須保存在一個workspace中。一個workspace必需要在根目錄下包含三個子目錄: 
* src 包含了Go的源文件,這些源文件以package的方式存在 
* pkg 包含了包對象 
* bin 包含了可執行文件
github

Go工具會編譯源文件並把編譯成的二進制文件存放在pkg和bin目錄中。golang

以下是一個典型的go項目的目錄:windows

bin/
    hello                           # 命令可執行文件 outyet # 命令可執行文件 pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # 包對象 src/ github.com/golang/example/ .git/ hello/ hello.go # 源文件 outyet/ main.go # 源文件 main_test.go # 測試 源文件 stringutil/ reverse.go # 源文件 reverse_test.go # 測試 源文件

這個workspace只包含了一個代碼庫(example),其中包含了兩個包hellooutyet以及一個庫stringutilruby

一個典型的workspace能夠包含多個代碼庫,以及每一個庫中的多個包和庫。多數的Go開發者把這些都放在一個單獨的workspace中。bash

包和庫是從不一樣的源文件包中編譯而成的。咱們會稍後討論這一點。架構

GOPATH環境變量

GOPATH環境變量指定的就是你的workspace的位置。這個很可能是你開發Go項目的時候惟一的一個須要設定的環境變量。框架

開始前先建立一個workspace目錄,而後在GOPATH中指定這個workspace目錄的位置。你能夠把GOPATH指定在任何的你喜歡的位置。 
可是本文會使用$HOME/work爲workspace目錄的位置。注意,這個目錄絕對不能夠和你的go的安裝目錄相同

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

而後把workspace的bin目錄添加到PATH中。

$ export PATH=$PATH:$GOPATH/bin

包路徑

標準庫的包路徑都會用簡寫:"fmt""net/http"。你本身的包就須要選擇一個路徑了。由於,你不會但願之後和標準庫的包或者其餘 
使用的包的名稱互相沖突的。

若是你把你的代碼保存在某代碼庫中,那麼你應該使用這個代碼庫的根做爲目錄使用: 

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

###你的第一個程序 
要編譯、運行你的程序,首先選擇一個包路徑(咱們會使用github.com/user/hello)並在你的workspace裏建立一個相應的包路徑 

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

而後,建立一個hello.go的文件。並在這個文件中添加以下的代碼: 
「`go 
package main

import 「fmt」

func main() { 
fmt.Println(「Hello, world!」) 
} 
「`

如今你能夠編譯並運行你的代碼了: 

go install github.com/user/hello 

注意你能夠在你的系統的任何地方來運行這個命令。go工具能夠根據GOPATH從workspace的github.com/user/hello找到源文件

上面的命令行執行以後,會在workspace的bin目錄下生成一個能夠自行文件,這裏是hello(或者,windows下的hello.exe)。在咱們的 
例子中目錄爲:$GOPATH/bin/hello

go工具只會在出錯的時候打印輸出信息。因此,若是沒有打印任何信息的話那就是編譯成功了。

如今你能夠運行你的程序了: 

$ $GOPATH/bin/hello 
Hello, world! 

或者,你已經在PATH中添加了GOPATH/bin,只須要輸入可執行文件的名字:

$ hello Hello, world!

若是你使用了代碼管理工具,那麼這就能夠初始化一個代碼庫了。添加文件;並commit你的第一次更改。可是,這不是必定要的,可是 
你能夠不用代碼工具編寫go代碼。

$ cd $GOPATH/src/github.com/user/hello $ git init Initialized empty Git respository 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

把代碼發佈到遠端代碼庫,讓其餘的讀者能夠看到你的代碼。

你的第一個庫

接下來,咱們建立一個庫,而後在hello代碼中使用這個庫。

按照常理咱們須要選擇一個包路徑(咱們這裏使用github.com/user/stringutil)並建立包路徑

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

而後,穿件一個文件:reverse.go, 內容爲:

package stringutil func Reverse(s string) string { var 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的代碼:

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

任什麼時候候go工具安裝一包或者一個二進制文件的時候,其相關的依賴也都會一塊兒安裝。所以,當你安裝hello的時候:

$ go install github.com/user/hello

stringutil包也會自動安裝。

運行新版本的程序,你會看到一個新的,反轉的消息:

$ hello Hello, Go!

以上的步驟都執行完成以後,你的目錄看起來是這樣的:

bin/
    hello
pkg/
    linux_amd64/
        github.com/user/ stringutil.a src/ github.com/user/ hello/ hello.go stringutil/ reverse.go

注意go installstringutil.a放在了pkg/linux_amd64目錄中,而且會在linux_amd64下建立和源文件所在的目錄相同的結構。 
go工具以後的編譯中若是發現pkg中已經存在這一文件,那麼就不會再次編譯。這樣能夠避免沒必要要的重複編譯。linux_amd64目錄是爲了交叉編譯 
,而且反映出所在的操做系統和系統架構。

Go的可執行文件是靜態連接的。

包名稱

Go的源文件第一行必須是:

package name

包名稱是import的時候使用的默認名稱,同一個包中的文件必須使用一樣的包名稱。

Go的慣例是包名稱是import語句的最後一個元素。crypto/rot13引入的包就應該命名爲rot13. 
main函數所在的包必須用package main做爲包名稱。

包的名稱沒有要求必需要惟一,可是報的整個引入路徑必需要惟一。

測試

Go有一個輕量級的測試框架,由go testtesting包組成。

寫一個測試只須要,建立一個_test.go結尾的文件,這個文件裏包含了名稱爲TestXXX的方法,這些測試方法的簽名爲func (t *testing.T)。 
測試框架會運行每個這樣的方法。若是某個測試方法調用了t.Error或者t.Fail, 那麼這個測試被認爲是失敗的。

給stringutil添加一個測試。在$GOPATH/src/github.com/user/sringutil/目錄建立文件reverse_test.go。這個文件包含 
以下代碼:

package stringutil import "testing" func TestReverse(t *testing.T) { case := []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", c.in, got, c.want) } } }

而後使用命令go test來運行測試:

$ go test github.com/user/stringutil PASS ok stringutil 2.223s 

若是實在package內部運行命令的話,能夠省去包的路徑。

$ go test PASS ok stringutil 2.223s

運行命令go help test能夠看到更多的關於測試命令的細節。

Remote packages 遠端代碼庫

一個import路徑和使用Git獲取遠程代碼的路徑是同樣的。go工具使用這個路徑自動從遠端代碼庫獲取代碼。好比,上面使用的代碼 
託管在GitHub的路徑爲:github.com/golang/example。若是在代碼的import語句中包含了遠端代碼,go get命令會自動獲取、編譯 
並install(安裝)這些代碼。

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

若是須要的包不在workspace中,go get命令會把這些包放在GOPATH指定的第一個workspace中。若是包已經存在,那麼go get 
命令會跳過遠程獲取而直接執行go install相似的命令。

在執行以上的go get命令以後,workspace目錄看起來就是這樣的:

bin/
    hello
pkg/
    linux_amd64/
        github.com/golang/example/ stringutil.a github.com/user/ stringutil.a src/ github.com/golang/example/ .git/ hello/ hello.a stringutil/ reverse.go reverse_test.go github.com/user/ hello/ hello.go stringutil/ reverse.go reverse_test.go

GitHub上託管的hello依賴於同一個包中的stringutilhello.go中的import語句使用的是同樣的慣例。所以go get命令 
能夠定位並安裝(install)依賴包。

import "github.com/golang/example/stringutil

這一慣例會讓你的代碼很是容易被別人使用。

接下來。。。

Effective Go有更多的關於有效編寫Go代碼的內容。

A Tour of Go有更多的關於Go的知識。

獲取幫助

這裏在官方的mailing list討論Go語言。

在這裏Go issue tracker提交bug。



原文

相關文章
相關標籤/搜索