天天看點

10.Go-包(Package)

包(package) 用于組織 Go 源代碼,提供了更好的可重用性與可讀性。Go 語言有超過 100 個的标準包,可以用

go list std | wc -l

指令檢視标準包的具體數目,标準庫為大多數的程式提供了必要的基礎元件。

10.1 main 包

首先,我們先來看看

main

包,該包中包含一個

main()

函數,該函數是程式運作的入口。

package packagename

代碼指定了某一源檔案屬于某一個包。它應該放在每一個源檔案的第一行。例如我們 Go 的第一個程式。

// hello go
package main

import "fmt"

func main() {
    fmt.Println("《Go語言極簡一本通》")
}
           

package main

這一行指定該檔案屬于

main

包。

import "fmt"

語句用于導入一個已存在的名為

fmt

的包。

10.2 建立包

下面我們建立自定義的

book

包,其中,屬于某一個包的源檔案都應該放置于一個單獨命名的檔案夾裡,按照 Go 的慣例,應該用包名命名該檔案夾。是以應當先建立一個

book

檔案夾,位于該目錄下建立一個

book.go

源檔案,裡面實作我們自定義的數學加法函數。請注意函數名的首字母要大寫。

// book.go
package book

func ShowBookInfo(bookName, authorName string) (string, error) {
	if bookName == "" {
		return "", errors.New("圖書名稱為空")
	}
	if authorName == "" {
		return "", errors.New("作者名稱為空")
	}
	return bookName + ",作者:" + authorName, nil
}
           

Tips:

  • 導出名字(Exported Names)
    • 我們将

      book

      包中的函數

      ShowBookInfo

      首字母大寫。在 Go 中這具有特殊意義。在 Go 中,任何以大寫字母開頭的變量或者函數都是被導出的名字。其它包隻能通路被導出的函數和變量。在這裡,我們需要在

      main

      包中通路

      ShowBookInfo

      函數,是以會将它們的首字母大寫。
    • 如果在

      book.go

      中将函數名從

      ShowBookInfo

      變為

      showBookInfo

      ,并且在

      main.go

      中調用

      book.showBookInfo

      函數,則該程式編譯不通過。因為如果想在包外通路一個函數,它應該首字母大寫。

10.3 導入包

使用包之前我們需要導入包,在 GoLand 中會幫你自動導入所需要的包。導入包的文法為

import path

,其中

path

可以是相對于工作區檔案夾的相對路徑,也可以是絕對路徑。

package main

import (
	"fmt"
	"book"
)

func main() {
	bookName := "《Go語言極簡一本通》"
	author := "歡喜"
	bookInfo, _ := book.ShowBookInfo(bookName, author)
	fmt.Println("bookInfo = ", bookInfo)
}
           

導入包可以單行導入也可以多行導入,像上面的程式代碼就是多行導入的例子,一般我們也建議使用多行導入,當然你也可以使用單行導入:

import "fmt"
import "book"
           

10.4 使用别名

如果我們導入了兩個具有同一包名的包時會産生沖突,這時我們可以為其中一個包定義别名:

import (
    "crypto/rand"
    mrand "math/rand" // 将名稱替換為 mrand 避免沖突
)
           

當然,我們也可以使用别名代替名字很長的包名。

10.5 使用點操作

導入一個包後,如果要使用該包中的函數,都要使用

包名.方法名

文法進行調用,對于一些使用高頻的包,例如

fmt

包,每次調用列印函數時都要使用

fmt.Println()

進行調用,很不友善。我們可以在導入包的時,使用

import . package_path

文法。從此,我們列印再也不用加

fmt

了。

import . "fmt"

func main() {
    Println("hello, world")
}
           

但這種用法,會有一定的隐患,就是導入的包裡可能有函數,會和我們自己的函數發生沖突。

10.6 包的初始化

每個包都允許有一個或多個

init

函數,

init

函數不應該有任何傳回值類型和參數,在代碼中也不能顯式調用它,當這個包被導入時,就會執行這個包的

init

函數,做初始化任務,

init

函數優先于

main

函數執行。該函數形式如下:

func init() {
}
           

包的初始化順序:首先初始化 包級别(Package Level) 的變量,緊接着調用

init

函數。包可以有多個

init

函數(在一個檔案或分布于多個檔案中),它們按照編譯器解析它們的順序進行調用。如果一個包導入了另一個包,會先初始化被導入的包。盡管一個包可能會被導入多次,但是它隻會被初始化一次。

10.7 包的匿名導入

import _ "fmt"