開始編寫Golang代碼


介紹

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

Go的工具需要將代碼按照一定的方式來組織。所以請認真閱讀本文。

代碼的組織

workspace

go工具是設計用來處理公開代碼庫的開源代碼的,雖然你不是一定要公開你的代碼,但是工作的模式是一樣的。

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

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

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

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以及一個庫stringutil

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

包和庫是從不同的源文件包中編譯而成的。我們會稍后討論這一點。

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。



原文 


免責聲明!

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



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