開始編寫Golang代碼

開始編寫Golang代碼

介紹

本文主要講述如何寫一個(gè)簡單的Go包和如何使用golang的工具熊痴,如何獲取把鉴、編譯和安裝Go的包蜂林,以及如何使用go的命令叔磷。

Go的工具需要將代碼按照一定的方式來組織阵具。所以請(qǐng)認(rèn)真閱讀本文碍遍。

代碼的組織

workspace

go工具是設(shè)計(jì)用來處理公開代碼庫的開源代碼的,雖然你不是一定要公開你的代碼阳液,但是工作的模式是一樣的怕敬。

Go代碼必須保存在一個(gè)workspace中。一個(gè)workspace必須要在根目錄下包含三個(gè)子目錄:

  • src 包含了Go的源文件帘皿,這些源文件以package的方式存在
  • pkg 包含了包對(duì)象
  • bin 包含了可執(zhí)行文件

Go工具會(huì)編譯源文件并把編譯成的二進(jìn)制文件存放在pkg和bin目錄中东跪。

如下是一個(gè)典型的go項(xiàng)目的目錄:

bin/
    hello                           # 命令可執(zhí)行文件<br/>
    outyet                          # 命令可執(zhí)行文件
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a            # 包對(duì)象
src/
    github.com/golang/example/
        .git/
        hello/
            hello.go                # 源文件
        outyet/
            main.go                 # 源文件
            main_test.go            # 測(cè)試 源文件
        stringutil/
            reverse.go              # 源文件
            reverse_test.go         # 測(cè)試 源文件

這個(gè)workspace只包含了一個(gè)代碼庫(example),其中包含了兩個(gè)包hello和outyet以及一個(gè)庫stringutil鹰溜。

一個(gè)典型的workspace可以包含多個(gè)代碼庫虽填,以及每個(gè)庫中的多個(gè)包和庫。多數(shù)的Go開發(fā)者把這些都放在一個(gè)單獨(dú)的workspace中曹动。

包和庫是從不同的源文件包中編譯而成的斋日。我們會(huì)稍后討論這一點(diǎn)。

GOPATH環(huán)境變量

GOPATH環(huán)境變量指定的就是你的workspace的位置墓陈。這個(gè)極可能是你開發(fā)Go項(xiàng)目的時(shí)候唯一的一個(gè)需要設(shè)定的環(huán)境變量恶守。

開始前先創(chuàng)建一個(gè)workspace目錄,然后在GOPATH中指定這個(gè)workspace目錄的位置贡必。你可以把GOPATH指定在任何的你喜歡的位置兔港。

但是本文會(huì)使用$HOME/work為workspace目錄的位置。注意仔拟,這個(gè)目錄絕對(duì)不可以和你的go的安裝目錄相同衫樊。

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

然后把workspace的bin目錄添加到PATH中。

$ export PATH=$PATH:$GOPATH/bin

包路徑

標(biāo)準(zhǔn)庫的包路徑都會(huì)用簡寫:“fmt”和“net/http”理逊。你自己的包就需要選擇一個(gè)路徑了橡伞。因?yàn)椋悴粫?huì)希望以后和標(biāo)準(zhǔn)庫的包或者其他
使用的包的名稱互相沖突的晋被。如果你把你的代碼保存在某代碼庫中兑徘,那么你應(yīng)該使用這個(gè)代碼庫的根作為目錄使用:

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

你的第一個(gè)程序

要編譯、運(yùn)行你的程序羡洛,首先選擇一個(gè)包路徑(我們會(huì)使用github.com/user/hello)并在你的workspace里創(chuàng)建一個(gè)相應(yīng)的包路徑

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

然后挂脑,創(chuàng)建一個(gè)hello.go的文件藕漱。并在這個(gè)文件中添加如下的代碼:


package main

import “fmt”

func main() {

fmt.Println(“Hello, world!”)

}

現(xiàn)在你可以編譯并運(yùn)行你的代碼了:

go install github.com/user/hello

注意你可以在你的系統(tǒng)的任何地方來運(yùn)行這個(gè)命令。go工具可以根據(jù)GOPATH從workspace的github.com/user/hello找到源文件
上面的命令行執(zhí)行之后崭闲,會(huì)在workspace的bin目錄下生成一個(gè)可以自行文件肋联,這里是hello(或者,windows下的hello.exe)刁俭。在我們的
例子中目錄為:$GOPATH/bin/hello橄仍。

go工具只會(huì)在出錯(cuò)的時(shí)候打印輸出信息。所以牍戚,如果沒有打印任何信息的話那就是編譯成功了侮繁。
現(xiàn)在你可以運(yùn)行你的程序了:

$ $GOPATH/bin/hello 
Hello, world! 

或者,你已經(jīng)在PATH中添加了GOPATH/bin如孝,只需要輸入可執(zhí)行文件的名字:

$ hello
Hello, world!

如果你使用了代碼管理工具宪哩,那么這就可以初始化一個(gè)代碼庫了。添加文件第晰;并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

把代碼發(fā)布到遠(yuǎn)端代碼庫,讓其他的讀者可以看到你的代碼腹躁。

你的第一個(gè)庫

接下來桑包,我們創(chuàng)建一個(gè)庫,然后在hello代碼中使用這個(gè)庫纺非。
按照常理我們需要選擇一個(gè)包路徑(我們這里使用github.com/user/stringutil)并創(chuàng)建包路徑

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

然后哑了,穿件一個(gè)文件:reverse.go, 內(nèi)容為:

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)
}

現(xiàn)在,用go build命令測(cè)試一下代碼是否能夠編譯烧颖。

$ go build github.com/user/stringutil

或者你在這個(gè)包的路徑下的話只需要:

$ go build

這不會(huì)生成任何文件弱左。要生成文件的話就必須要使用go install。執(zhí)行完這個(gè)命令之后就會(huì)把這個(gè)包編譯后生成在pkg目錄中炕淮。
在stringutil編譯之后拆火,修改hello.go的代碼:

package main

import (
    “fmt”
    “github.com/user/stringutil”
)

func main() {
    fmt.Println(stringutil.Reverse(“!oG ,olleH”))
}

任何時(shí)候go工具安裝一包或者一個(gè)二進(jìn)制文件的時(shí)候,其相關(guān)的依賴也都會(huì)一起安裝涂圆。因此们镜,當(dāng)你安裝hello的時(shí)候:

$ go install github.com/user/hello

stringutil包也會(huì)自動(dòng)安裝。運(yùn)行新版本的程序润歉,你會(huì)看到一個(gè)新的模狭,反轉(zhuǎn)的消息:

$ hello

Hello, Go!

以上的步驟都執(zhí)行完成之后,你的目錄看起來是這樣的:

bin/
    hello

pkg/
linux_amd64/
github.com/user/
stringutil.a

src/
github.com/user/
hello/
hello.go
stringutil/
reverse.go

注意go install把stringutil.a放在了pkg/linux_amd64目錄中踩衩,并且會(huì)在linux_amd64下創(chuàng)建和源文件所在的目錄相同的結(jié)構(gòu)嚼鹉。
go工具之后的編譯中如果發(fā)現(xiàn)pkg中已經(jīng)存在這一文件贩汉,那么就不會(huì)再次編譯。這樣可以避免不必要的重復(fù)編譯锚赤。linux_amd64目錄是為了交叉編譯
匹舞,并且反映出所在的操作系統(tǒng)和系統(tǒng)架構(gòu)。

Go的可執(zhí)行文件是靜態(tài)鏈接的线脚。

##包名稱

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

package name

包名稱是import的時(shí)候使用的默認(rèn)名稱赐稽,同一個(gè)包中的文件必須使用同樣的包名稱。
Go的慣例是包名稱是import語句的最后一個(gè)元素浑侥。crypto/rot13引入的包就應(yīng)該命名為rot13.
main函數(shù)所在的包必須用package main作為包名稱又憨。
包的名稱沒有要求必須要唯一,但是報(bào)的整個(gè)引入路徑必須要唯一锭吨。

##測(cè)試

Go有一個(gè)輕量級(jí)的測(cè)試框架,由go test和testing包組成寒匙。
寫一個(gè)測(cè)試只需要零如,創(chuàng)建一個(gè)_test.go結(jié)尾的文件,這個(gè)文件里包含了名稱為TestXXX的方法锄弱,這些測(cè)試方法的簽名為func (t *testing.T)考蕾。
測(cè)試框架會(huì)運(yùn)行每一個(gè)這樣的方法。如果某個(gè)測(cè)試方法調(diào)用了t.Error或者t.Fail, 那么這個(gè)測(cè)試被認(rèn)為是失敗的会宪。
給stringutil添加一個(gè)測(cè)試肖卧。在$GOPATH/src/github.com/user/sringutil/目錄創(chuàng)建文件reverse_test.go赋除。這個(gè)文件包含
如下代碼:
```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來運(yùn)行測(cè)試:

$ go test github.com/user/stringutil

PASS
ok          stringutil          2.223s 

如果實(shí)在package內(nèi)部運(yùn)行命令的話汹忠,可以省去包的路徑。

$ go test

PASS
ok          stringutil          2.223s

運(yùn)行命令go help test可以看到更多的關(guān)于測(cè)試命令的細(xì)節(jié)沪羔。

Remote packages 遠(yuǎn)端代碼庫

一個(gè)import路徑和使用Git獲取遠(yuǎn)程代碼的路徑是一樣的巍沙。go工具使用這個(gè)路徑自動(dòng)從遠(yuǎn)端代碼庫獲取代碼葵姥。比如,上面使用的代碼
托管在GitHub的路徑為:github.com/golang/example句携。如果在代碼的import語句中包含了遠(yuǎn)端代碼榔幸,go get命令會(huì)自動(dòng)獲取、編譯
并install(安裝)這些代碼矮嫉。

$ go get github.com/golang/example/hello

$ $GOPATH/bin/hello
Hello, Go examples!

如果需要的包不在workspace中削咆,go get命令會(huì)把這些包放在GOPATH指定的第一個(gè)workspace中。如果包已經(jīng)存在蠢笋,那么go get

命令會(huì)跳過遠(yuǎn)程獲取而直接執(zhí)行go install類似的命令拨齐。

在執(zhí)行以上的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依賴于同一個(gè)包中的stringutil挺尿。hello.go中的import語句使用的是一樣的慣例奏黑。因此go get命令
可以定位并安裝(install)依賴包炊邦。
import “github.com/golang/example/stringutil
這一慣例會(huì)讓你的代碼非常容易被別人使用。

接下來熟史。馁害。。

Effective Go有更多的關(guān)于有效編寫Go代碼的內(nèi)容蹂匹。

A Tour of Go有更多的關(guān)于Go的知識(shí)碘菜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市限寞,隨后出現(xiàn)的幾起案子忍啸,更是在濱河造成了極大的恐慌,老刑警劉巖履植,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件计雌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡玫霎,警方通過查閱死者的電腦和手機(jī)凿滤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來庶近,“玉大人翁脆,你說我怎么就攤上這事”侵郑” “怎么了反番?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長叉钥。 經(jīng)常有香客問我罢缸,道長,這世上最難降的妖魔是什么投队? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任祖能,我火速辦了婚禮,結(jié)果婚禮上蛾洛,老公的妹妹穿的比我還像新娘养铸。我一直安慰自己,他們只是感情好轧膘,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布钞螟。 她就那樣靜靜地躺著,像睡著了一般谎碍。 火紅的嫁衣襯著肌膚如雪鳞滨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天蟆淀,我揣著相機(jī)與錄音拯啦,去河邊找鬼澡匪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛褒链,可吹牛的內(nèi)容都是我干的唁情。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼甫匹,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼甸鸟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兵迅,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤抢韭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后恍箭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刻恭,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年扯夭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吠各。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勉抓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出候学,到底是詐尸還是另有隱情藕筋,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布梳码,位于F島的核電站隐圾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏掰茶。R本人自食惡果不足惜暇藏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望濒蒋。 院中可真熱鬧盐碱,春花似錦、人聲如沸沪伙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽围橡。三九已至暖混,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翁授,已是汗流浹背拣播。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工晾咪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贮配。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓谍倦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親牧嫉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剂跟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容