如何正確的開始用 Go 編程

如何正確的開始用 Go 編程

本文會演示簡單的Go軟件包的開發過程,並介紹了go命令行工具,這是咱們獲取,構建和安裝Go軟件包和命令的標準方法。git

go工具要求你以特定方式組織代碼。咱們會介紹Go安裝啓動和運行的最簡單方法,必定要仔細閱讀啊。程序員

組織代碼結構

概要

  • Go 程序員通常會將他們的源代碼存放在一個工做區中(多個項目放在一個工做區)
  • 工做區中包含許多由 git 管理的代碼倉庫(也能夠是其餘版本控制工具管理的)
  • 每一個代碼倉庫包含一個或者多個 Go package
  • 每一個 package 由單一目錄下的一個或多個Go 源碼文件組成
  • package 的目錄路徑決定了其導入路徑

與其餘編程語言不一樣的是,在其餘編程語言裏每一個項目都有本身的工做區,而且工做區都與版本控制系統緊密相關。github

工做區

工做區是一個目錄層級,這個目錄層級在頂層有兩個目錄:golang

  1. src 目錄,存放源代碼文件。
  2. bin 目錄,存放可執行二進制文件。

go命令工具會把src中的Go 文件構建生成二進制文件放在bin目錄中。shell

src子目錄一般包含用 git 管理的多個代碼倉庫,他們對應一個或多個Go 包的開發源碼。編程

一個典型的工做區中會包含多個源碼倉庫,對應多個可執行命令源碼和包源碼。大多數 Go 程序員會把他們的Go 源碼和全部依賴的包都放在單一的工做區中。緩存

下面的例子可讓你更好的瞭解Go 的工做區大概的樣子:框架

bin/
    hello                          # 可執行命令文件
    outyet                         # 可執行命令文件
src/
    github.com/golang/example/
          .git/                      
          hello/
              hello.go               # 命令文件源碼
          outyet/
              main.go                # 命令文件源碼
              main_test.go           # 測試文件
          stringutil/
              reverse.go             # package源碼
              reverse_test.go        # 測試文件
    golang.org/x/image/
          .git/               
          bmp/
            reader.go              # package 源碼
            writer.go              # package 源碼
  ......

上面的目錄樹展現了工做區中的兩個代碼倉庫(example 和 image)。example 倉庫中包含兩個命令hello 和 outyet(hello 和 outyet 目錄中存放的就是兩個命令的源碼)一個被用做庫的 package - stirngutil 。image倉庫中包含一個bmp包。編程語言

注意:不能使用符號連接(軟鏈 ln -s)將文件連接到工做區中。函數

執行命令和庫是從不一樣類的源碼包構建出來的,這個以後的部分會進行說明。

GOPATH 環境變量

GOPATH環境變量指定工做區的位置。它缺省爲用戶目錄中名爲go的目錄,所以在Linux上爲$HOME/go,在Windows上一般爲C:\Users\YourName\Go

若是想在其餘位置放置工做區,則須要將GOPATH設置爲該目錄的路徑。請注意,GOPATH不得與GO安裝路徑相同。

命令go env GOPATH打印當前有效的GOPATH;若是環境變量未設置,它將打印默認位置。爲方便起見,能夠請將工做區的bin子目錄添加到系統環境變量$PATH

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

同時也把GOPATH設置成系統的環境變量:

$ export GOPATH=$(go env GOPATH)

包的導入路徑

一個導入路徑是用來惟一標識包的字符串,包的導入路徑和他在工做區中的位置相對應。標準庫中的包具備較短的導入路徑,如「fmt」和「net/http」。對於您本身的軟件包,你必須選擇一個不太可能與未來添加到標準庫或其餘外部庫中的內容衝突的基本路徑。

若是你將代碼保存在某個源代碼庫中,那麼應該使用該源代碼庫的根目錄做爲你的基本路徑。例如,若是你在github.com上有一個GitHub賬戶user,你建立的倉庫都會以 github.com/user 爲前綴,那麼github.com/user這應該是你的基本路徑。

請注意,在構建代碼以前,你不須要將代碼發佈到遠程存儲庫。就像有一天會發布代碼同樣來組織代碼,這是一個好習慣。實際上,您能夠選擇任意路徑名,只要它是惟一的。

咱們將使用github.com/user做爲基本路徑。在工做區內建立一個保存源代碼的目錄:

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

你的第一個Go程序

要編譯並運行一個簡單的程序,首先選擇一個軟件包路徑(咱們將使用github.com/user/hello),並在您的工做區內建立一個相應的軟件包目錄:

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

接下來,在該目錄中建立一個名爲hello.go的文件,添加如下代碼:

package main

import "fmt"

func main() {
    fmt.Println("Hello, world.")
}

如今,你可使用go工具構建和安裝該程序了:

$ go install github.com/user/hello

你能夠從系統上的任何位置運行此命令。go命令工具經過在GOPATH指定的工做區內查找github.com/user/hello包來查找源代碼。若是從軟件包目錄運行go Install,能夠省略軟件包路徑:

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

go install構建hello命令,生成一個可執行的二進制文件。而後,它將該二進制文件做爲hello(在Windows下爲hello.exe)安裝到工做區的bin目錄中,hello 可執行命令的位置爲 $GOPATH/bin/hello

Go工具僅在發生錯誤時打印輸出,所以若是這些命令沒有產生輸出,則表明它們已成功執行。

如今,你能夠經過在命令行中鍵入程序的完整路徑來運行該程序:

$ $GOPATH/bin/hello
Hello, world.

因爲您已將$GOPATH/bin添加到路徑中,所以只需鍵入二進制文件的名字:

$ hello
Hello, world.

你的第一個 library

讓咱們編寫一個庫並在上面寫的hello程序中使用它。

一樣,第一步是選擇軟件包路徑(咱們將使用github.com/user/stringutil)並建立軟件包目錄:

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

接下來在目錄中建立reverse.go文件並添加以下代碼:

// stringutil包 存放關於字符串的工具函數 
package stringutil

// Reverse 將參數中的字符串反轉後的字符串
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不會產生輸出文件。相反,它將編譯後的包保存在本地構建緩存中。

在確認stringutil包構建能夠正確以後,修改原始的hello.go(位於$GOPATH/src/github.com/user/hello中)以使用它:

package main

import (
    "fmt"

    "github.com/user/stringutil"
)

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

再次編譯安裝 hello 程序後運行他,能夠看到輸出中的字符串已經被反轉了。

$ hello
Hello, Go!

通過上面幾步後你的工做區如今應該看起來像下面這樣:

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

包名

go 源碼文件中的第一行語句必須是:

package name

其中,name是用於導入的包的默認名稱。(包中的全部文件必須使用相同的名稱)

go的慣例是包名是導入路徑的最後一個元素:做爲「crypto/rot13」導入的包它的包名爲rot13

生成可執行命令的源碼文件必須以 main做爲包名。

go 中不要求連接到單個二進制文件的全部包的包名都是惟一的,只要求導入路徑(它們的完整文件名)是惟一的。

測試

go有一個由go測試命令和測試包組成的輕量級測試框架。你能夠經過建立一個名字以_test.go結尾的文件來編寫測試,該文件包含名爲TestXXX的函數,簽名函數爲func(t*testing.T)。測試框架運行每一個這樣的函數;若是函數調用失敗函數,如t.Error或t.Fail,則認爲測試失敗。

經過建立包含如下go代碼的文件$GOPATH/src/github.com/user/stringutil/reverse_test.go,將測試添加到strangutil包。

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

而後使用go test運行測試

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

導入路徑能夠描述如何從版本控制系統(如Git)獲取包源代碼。Go工具使用此屬性自動從遠程倉庫中獲取包。例如,本文檔中描述的示例也保存在GitHub 以github.com/golang/example託管的Git存儲庫中。若是將代碼倉庫的URL包含在軟件包的導入路徑中,go將會使用go get`自動獲取、構建和安裝它:

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

若是工做區中沒有指定的包,go get將把它放在$GOPATH指定的工做區中。(若是軟件包已經存在,go get將跳過遠程獲取,其行爲變得與go install相同。)。

發出上述go get命令後,工做區目錄樹如今應該以下所示:

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

託管在GitHub上的hello命令依賴於同一倉庫中的stringutil包。hello.go文件中的導入使用相同的導入路徑約定,所以go get命令也可以定位和安裝依賴包。

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

What's Next

WX20191117-152623@2x.png

相關文章
相關標籤/搜索