How to Write GO Code 中文版

How to Write GO Code 中文版

  • 說明

    • 官方原文
    • 本文按個人理解進(jìn)行意譯,水平有限,難免有錯或偏差,歡迎批評指正
  • 目錄

    • Introduction

    • Code Organization

      • overview
      • workspace
      • the GOPATH environment variable
      • import paths
      • your first program
      • your first library
      • package names
    • Testing

    • remote packages

    • what`s next

    • getting help

introduction

  • Go語言要求使用指定的方法組織代碼。
  • 需要認(rèn)真閱讀這份文檔。

Code Organization

overview

  • 通常來說Go開發(fā)者將他所有的源代碼放到一個單獨(dú)的工作目錄中

  • 一個工作目錄中包含多版本控制倉庫

  • 每個倉庫包含一個或者多個包

  • 每個包在一個單路的目錄中包含一個或者多個GO源代碼文件

  • 到包的路徑?jīng)Q定了它import的路徑

需要注意,這一點(diǎn),與其他語言編程環(huán)境中每一個項(xiàng)目都放在一個分開的單獨(dú)工作目錄并且每個工作目錄都有一個倉庫版本控制,是不同的

workspace

一個工作目錄是一個層次結(jié)構(gòu)目錄,在其根目錄包含以下三個目錄

  • src 包含Go語言的源代碼文件
  • pkg 包含包對象
  • bin 包含可執(zhí)行文件

go工具構(gòu)建源代碼并將生成的二進(jìn)制文件放到 pkg 和 bin 目錄中。

src 子目錄通常包含多版本控制倉庫來追蹤一個或者多個源包的開發(fā)過程。

下面是個實(shí)際中的關(guān)于工作空間的簡要例子:

bin/
    hello                          # command executable
    outyet                         # command executable
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a           # package object
src/
    github.com/golang/example/
        .git/                      # Git repository metadata
    hello/
        hello.go               # command source
    outyet/
        main.go                # command source
        main_test.go           # test source
    stringutil/
        reverse.go             # package source
        reverse_test.go        # test source
    golang.org/x/image/
        .git/                      # Git repository metadata
    bmp/
        reader.go              # package source
        writer.go              # package source
    ... (many more repositories and packages omitted) ...

上面的結(jié)構(gòu)樹展示了一個工作空間包含兩個倉庫(example和image)。example庫包含兩個可執(zhí)行目錄(hello和outyet)和一個庫(stringutil)。image倉庫包含bmp包和幾個其他包

一個典型的工作空間包含了內(nèi)含許多包和命令的倉庫。絕大多數(shù)的go開發(fā)者將他們的源代碼和依賴都放到一個工作空間中。

命令和庫 是從不同的源碼包構(gòu)建而來。

the GOPATH environment variable

GOPATH 環(huán)境變量指明了工作空間的位置。它默認(rèn)是在你的主目錄中的一個名為go的目錄, 所以在Linux下就是$HOME/go, 在plan9下就是$home/go, 在Windows下就是%USERPROFILE%/go(通過是C:\Users\YourName\go).

如果想在一個不同的目錄下工作,需要 設(shè)置 GOPATH 到想指定的目錄.(另一個通常的設(shè)置是設(shè)置 GOPATH=$HOME).<strong>需要注意的是 GOPATH 和 go的安裝目錄不能相同</strong>.

為了方便,添加工作空間的 bin 子目錄到path:

$ export PATH=$PATH:$(go env GOPATH)/bin

為了簡短一點(diǎn),上面腳本在本文末使用 $GOPATH 替換 $(go env GOPATH).

要學(xué)習(xí)更多關(guān)于GOPATH環(huán)境變量相關(guān)的信息,查看 go help gopath

要使用通用工作空間位置,查看 GOPATH 環(huán)境變量

import paths

一個導(dǎo)入路徑 import path 是唯一性地標(biāo)志一個包的字符串。一個包的import path對應(yīng)它在工作空間中的位置或者一個遠(yuǎn)程倉庫.

標(biāo)準(zhǔn)庫中的包通常都給定一個比如 "fmt"或者"net/http"這樣簡短的import path. 對于你自己的包,需要選一個不會跟未來被添加到標(biāo)準(zhǔn)庫或者其他拓展庫的命名沖突的基礎(chǔ)路徑。

我們選擇 github.com/user 作為我們的基礎(chǔ)路徑,然后在工作空間中創(chuàng)建愛你一個目錄來保存源代碼:

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

your first program

為了編譯和運(yùn)行一個簡單的程序,首先選一個包路徑(我們將使用 github.com/user/hello)然后在工作目錄中創(chuàng)建一個對應(yīng)的包目錄

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

然后,在那個目錄里面創(chuàng)建一個文件,命名為 hello.go,并把下面的代碼放上去:

package main

import "fmt"

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


現(xiàn)在,可以使用go tool 來 build 并且安裝上面的程序了:

$ go install github.com/user/hello

你可以在你系統(tǒng)的任務(wù)地方運(yùn)行上面的命令. go tool 會根據(jù) GOPATH 指明的工作空間到 github.com/user/hello 包中找到源代碼.

如果從包目錄中運(yùn)行 go install,你可以忽略掉包的路徑:

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

上面的命令將會構(gòu)建 hello 命令,產(chǎn)生一個可執(zhí)行二進(jìn)制文件。然后將二進(jìn)制文件以hello名字安裝到工作空間的 bin 目錄下(在 Windows下是 hello.exe)。在我們的例子中就是 $GOPATH/bin/hello, 也就是 $HOME/go/bin/hello.

go 工具只有在產(chǎn)生錯誤時才打印輸出,所以如果上面的命令執(zhí)行之后沒有產(chǎn)生任何打印輸出,那就是執(zhí)行成功了。

現(xiàn)在可以通過全路徑運(yùn)行命令:

$ $GOPATH/bin/hello
Hello, world

或者也可以添加 $GOPATH/bin到你的 PATH,然后運(yùn)行二進(jìn)制文件就可以執(zhí)行命令了:

$ hello
Hello, world

your first library

選擇一個包路徑(在這我們將使用 github.com/user/stringutil)然后創(chuàng)建一個包目錄來寫一個庫并使用:

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

接著在上面目錄中創(chuàng)建一個名為 reverse.go 的文件并放上一下內(nèi)容:

// 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 來編譯上面創(chuàng)建的包:

$ go build github.com/user/stringutil

或者, 如果你是在上面的包的目錄下的話,直接運(yùn)行下面的命令:

$ go build

上面的命令不會產(chǎn)生一個文件。如果想要產(chǎn)生文件,必須使用 go install,這樣的話會在工作空間的 pkg 的目錄中產(chǎn)生一個包對象。

確認(rèn) stringutil 包被構(gòu)建之后,更改hello.go(在$GOPATH/src/github.com/user/hello目錄下)來使用它

package main

import (
    "fmt"

    "github.com/user/stringutil"
)

func main() {
    fmt.Printf(stringutil.Reverse("!oG ,olleH"))
}

任何時候 go tool 安裝了一個包或者二進(jìn)制文件, 包或者二進(jìn)制文件里面的所有依賴也會被安裝,所以當(dāng)安裝 hello 程序, stringutil 包也同時會自動被安裝

$go install github.com/user/hello

執(zhí)行新版本的程序,應(yīng)該可以看到一個新的信息

$ hello
 Hello, Go!

上面所有的步驟執(zhí)行完之后,工作空間看起來應(yīng)該是下面這樣的:

bin/
    hello                 # command executable
pkg/
    linux_amd64/          # this will reflect your OS and architecture
        github.com/user/
            stringutil.a  # package object
src/
    github.com/user/
        hello/
            hello.go      # command source
        stringutil/
            reverse.go    # package source

注意 go install 將 stringutil.a 對象放在 pkg/linux_amd64 里面的一個目錄下,來映射它的源目錄。這樣方便以后 go tool 可以找到包對象并避免對包進(jìn)行不必要的重編譯。linux_amd64可以幫助交叉編譯,并反映操作系統(tǒng)和系統(tǒng)的結(jié)構(gòu)。

Go 命令可執(zhí)行文件是靜態(tài)鏈接的:運(yùn)行 Go 程序不需要包對象的存在

package names

Go 源文件的第一條語句必須是:

package name

name 是包的導(dǎo)入默認(rèn)名字(其他文件導(dǎo)入這個包時使用的名稱)(一個包中的所有文件都必須是相同的name

Go 的慣例是包名是導(dǎo)入路徑的最后一個元素。如果被導(dǎo)入的包是cryto/rot13那么包的名字應(yīng)該是 rot13。

可執(zhí)行命令必須使用總是使用 package main。

被鏈接到一個單個二進(jìn)制文件的所有包,這些包的名稱不要求名字唯一性,但是包的導(dǎo)入路徑要求內(nèi)唯一性(文件完整名稱)

查看 Effective Go 來了解更多信息

Testing

Go 有一個由 go test 命令和 testing 包組成的輕量級的測試框架.

創(chuàng)建一個以 _test.go為文件名后綴的文件,文件中包含名為 TestXXX 的簽名 func (t *testing.T)的函數(shù),通過這樣的方式來編寫測試。測試框架運(yùn)行每一個這樣的函數(shù),如果函數(shù)調(diào)用類似 t.Error 或者 t.Fail 的報錯函數(shù),那么說明這里面對應(yīng)的測試用例已經(jīng)失敗.

創(chuàng)建 $GOPATH/src/github.com/user/stringutil/reverse_test.go文件,把下面的代碼放上去,這樣就為 stringutil包添加了測試.

package stringutil

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

運(yùn)行下面的命令來跑測試:

$ go test github.com/user/stringutil
ok github.com/user/stringutil 0.165s

另外,如果你是在包的目錄下的話,不用跑上面的命令,直接跑下面的命令即可

$ go test
ok github.com/user/stringutil 0.165s

運(yùn)行 go helo test 以及查看 testing package documentation來了解更多信息

remote packages

一個導(dǎo)入路徑可以描述如何通過使用比如git或者marcurial這樣的版本控制系統(tǒng)來獲取包的源代碼。go tool 使用這個特性來自動從遠(yuǎn)處倉庫獲取包。舉個栗子,在這個文檔中描述的包同時是一個托管在 github.com/golang/example 的Git倉庫。如果在包的導(dǎo)入路徑中包含這個倉庫的URL,那么, go get 會自動地獲取,構(gòu)建,然后安裝它:

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

如果指定的包沒有出現(xiàn)在工作空間中,go get 將會把該指定的包放置通過GOPATH指定的第一個工作空間中。(如果該包早已經(jīng)存在將要被放置的工作空間中,go get 將會跳過從遠(yuǎn)程倉庫獲取的過程從而繼續(xù)執(zhí)行g(shù)o install)

執(zhí)行完上面 go get 命令之后,工作空間的目錄樹看起來應(yīng)該是下面這樣的:

bin/
    hello                           # command executable
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a            # package object
        github.com/user/
            stringutil.a            # package object
src/
    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 文件中的導(dǎo)入使用相同的導(dǎo)入路徑約定,因此 go get 也可以找到并安裝依賴的包。

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

這個約定是讓你的go 包可以被其他go開發(fā)者使用的最簡單的方法。Go wikigodoc.org提供里go的拓展項(xiàng)目.

想要了解更多的關(guān)于使用 go tool 來獲取遠(yuǎn)程倉庫的信息,查看go help importpath

what`s next

看一下 Effective Go

看一下 A Tour of Go

看一下 documentation page

getting help

如果需要實(shí)時幫助,訪問Freenode

官方關(guān)于go的探討的郵件列表在Go Nuts

有bug想上報?到Go issue tracker

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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