goalng包和命令工具

1. 包簡介

任何包系統設計的目的都是爲了簡化大型程序的設計和維護工做,經過將一組相關的特性放進一個獨立的單元以便於理解和更新,在每一個單元更新的同時保持和程序中其它單元的相對獨立性。這種模塊化的特性容許每一個包能夠被其它的不一樣項目共享和重用,在項目範圍內、甚至全球範圍統一的分發和複用。html

每一個包通常都定義了一個不一樣的名字空間用於它內部的每一個標識符的訪問。每一個名字空間關聯到一個特定的包,讓咱們給類型、函數等選擇簡短明瞭的名字,這樣能夠在使用它們的時候減小和其它部分名字的衝突。python

每一個包還經過控制包內名字的可見性和是否導出來實現封裝特性。經過限制包成員的可見性並隱藏包API的具體實現,將容許包的維護者在不影響外部包用戶的前提下調整包的內部實現。經過限制包內變量的可見性,還能夠強制用戶經過某些特定函數來訪問和更新內部變量,這樣能夠保證內部變量的一致性和併發時的互斥約束。mysql

2.包的導入

每一個包是由一個全局惟一的字符串所標識的導入路徑定位。出如今import語句中的導入路徑也是字符串。git

import (
    "fmt"
    "math/rand"
    "encoding/json"

    "golang.org/x/net/html"

    "github.com/go-sql-driver/mysql"
)

3. 包聲明

在每一個Go語言源文件的開頭都必須有包聲明語句。包聲明語句的主要目的是肯定當前包被其它包導入時默認的標識符(也稱爲包名)。github

一般來講,默認的包名就是包導入路徑名的最後一段,所以即便兩個包的導入路徑不一樣,它們依然可能有一個相同的包名。例如,math/rand包和golang.org/x/exp/rand包的包名都是randgolang

package main

import (
	"fmt"
	"math/rand"  
)
	// 導入rand包 用rand包裏的方法函數等
func main() {
	fmt.Println(rand.Int63n(10000))  // 9410
}
package main

import (
	"fmt"

	"golang.org/x/exp/rand"
)

func main() {
	fmt.Println(rand.Int63n(10000)) // 9351
}

4.導入聲明

若是咱們想同時導入兩個有着名字相同的包,例如math/rand包和golang.org/x/exp/rand包,那麼導入聲明必須至少爲一個同名包指定一個新的包名以免衝突。這叫作導入包的重命名。sql

package main

import (
	"fmt"
	rand1 "math/rand"

	rand2 "golang.org/x/exp/rand"
)

func main() {
	fmt.Println(rand1.Int63n(10000)) // 9401
	fmt.Println(rand2.Int63n(10000)) // 9351
}

5.包的匿名導入

若是隻是導入一個包而並不使用導入的包將會致使一個編譯錯誤。可是有時候咱們只是想利用導入包而產生的反作用:它會計算包級變量的初始化表達式和執行導入包的init初始化函數。這時候咱們須要抑制「unused import」編譯錯誤,咱們能夠用下劃線_來重命名導入的包。好比序號gorm包是要帶入sql驅動json

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

func main() {
  db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
  defer db.Close()
}

6. 包和命名

當建立一個包,通常要用短小的包名,但也不能過短致使難以理解。標準庫中最經常使用的包有bufiobytesflagfmthttpiojsonossortsynctime等包。session

包名通常採用單數的形式。標準庫的bytes、errors和strings使用了複數形式,這是爲了不和預約義的類型衝突,一樣還有go/types是爲了不和type關鍵字衝突。併發

7.工具

Go語言工具箱的具體功能,包括如何下載、格式化、構建、測試和安裝Go語言編寫的程序。

7.1. go命令

$ go
...
    build            compile packages and dependencies
    clean            remove object files
    doc              show documentation for package or symbol
    env              print Go environment information
    fmt              run gofmt on package sources
    get              download and install packages and dependencies
    install          compile and install packages and dependencies
    list             list packages
    run              compile and run Go program
    test             test packages
    version          print Go version
    vet              run go tool vet on packages

Use "go help [command]" for more information about a command.
...

7.2. 下載包

使用Go語言工具箱的go命令,不只能夠根據包導入路徑找到本地工做區的包,甚至能夠從互聯網上找到和更新包。

使用命令go get能夠下載一個單一的包或者用...下載整個子目錄裏面的每一個包。Go語言工具箱的go命令同時計算並下載所依賴的每一個包,這也是前一個例子中golang.org/x/net/html自動出如今本地工做區目錄的緣由。

7.3. 構建包

go build命令編譯命令行參數指定的每一個包。若是包是一個庫,則忽略輸出結果;這能夠用於檢測包是能夠正確編譯的。若是包的名字是main,go build將調用連接器在當前目錄建立一個可執行程序;以導入路徑的最後一段做爲可執行程序的名字。

7.4. 包文檔

Go語言的編碼風格鼓勵爲每一個包提供良好的文檔。包中每一個導出的成員和包聲明前都應該包含目的和用法說明的註釋。

Go語言中的文檔註釋通常是完整的句子,第一行一般是摘要說明,以被註釋者的名字開頭。註釋中函數的參數或其它的標識符並不須要額外的引號或其它標記註明。例如,下面是fmt.Fprintf的文檔註釋。

// Fprintf formats according to a format specifier and writes to w.
// It returns the number of bytes written and any write error encountered.
func Fprintf(w io.Writer, format string, a ...interface{}) (int, error)

首先是go doc命令,該命令打印其後所指定的實體的聲明與文檔註釋,該實體多是一個包:

$ go doc time
package time // import "time"

Package time provides functionality for measuring and displaying time.

const Nanosecond Duration = 1 ...
func After(d Duration) <-chan Time
func Sleep(d Duration)
func Since(t Time) Duration
func Now() Time
type Duration int64
type Time struct { ... }
...many more...

或者是某個具體的包成員:

$ go doc time.Since
func Since(t Time) Duration

    Since returns the time elapsed since t.
    It is shorthand for time.Now().Sub(t).

或者是一個方法:

$ go doc time.Duration.Seconds
func (d Duration) Seconds() float64

    Seconds returns the duration as a floating-point number of seconds.

7.5. 內部包

在Go語言程序中,包是最重要的封裝機制。沒有導出的標識符只在同一個包內部能夠訪問,而導出的標識符則是面向全宇宙都是可見的。

net/http
net/http/internal/chunked
net/http/httputil
net/url

7.6. 查詢包

go list命令能夠查詢可用包的信息。其最簡單的形式,能夠測試包是否在工做區並打印它的導入路徑:

$ go list github.com/go-sql-driver/mysql
github.com/go-sql-driver/mysql

go list命令還能夠獲取每一個包完整的元信息,而不只僅只是導入路徑,這些元信息能夠以不一樣格式提供給用戶。其中-json命令行參數表示用JSON格式打印每一個包的元信息。能夠用"..."表示匹配相關包的包的導入路徑。

$ go list ...mysql
github.com/astaxie/beego/session/mysql
github.com/go-sql-driver/mysql

參考文章:

  • 《go語言聖經》
相關文章
相關標籤/搜索