1. 程式人生 > 其它 >go 語言的包

go 語言的包

Go 語言包的基本概念

目錄

Go語言 包的基本概念


Go語言是使用包來組織原始碼的,包(package)是多個 Go 原始碼的集合,是一種高階的程式碼複用方案。Go語言中為我們提供了很多內建包,如 fmt、os、io 等。

包時結構化程式碼的一種方式:每個程式都是由包(通常簡稱為pkg)的概念組成,可以使用自身的包或者從其他包中匯入內容

如同其他一些程式語言中的類庫或者名稱空間的概念,每個Go檔案有且僅屬於一個包。一個包可以由許多以 .go為副檔名的原始檔組成,因此檔名和包名一般來說都是不同的。

必須在原始檔中非註釋的第一行指明這個檔案屬於與哪個包 package pacakgeName 語句,通過該語句宣告自己所在的包。package main 則表示一個可獨立執行的程勳,每個Go應用程式都包含一個名為main的包。

一個應用程式可以包含不同的包,而且即使只使用main包,也不必包所有的程式碼都寫在一個巨大的檔案裡:可以使用一些較小的檔案,並且在每個檔案非註釋的第一行使用package main來指明這些檔案檔案都屬於main包。如果打算編譯報名不是main的原始檔,如 pack1,編譯後產生的物件檔案將會是pack1.a而不是可執行程式。另外,要注意的是所有的包名都應該使用小寫字母


標準庫

標準庫API:https://studygolang.com/pkgdoc

在Go的安裝檔案裡包含了一些可以直接使用的包,即標準庫。在Windows 下,標準庫的位置在Go根目錄下的子目錄pkg\windoes_amd64中;在Linux下,標準庫在Go根目錄的子目錄 pkg\linux_amd64中.

一般情況下,標準包會存放在$GOROOT/pkg/\$GOOS_GOARCH/目錄下. GO的標準庫包含了大量的包,(如:fmt 和os),但是也可以建立自己的包

如果想要構建一個程式,則包和包內的檔案夠必須以正確的順序進行編譯。包的依賴關係決定了器構建順序。

屬於同一個包的原始檔必須全部一起被編譯

,一個包即是編譯時的一個單元,因此根據慣例,每個目錄都只包含一個包

如果對一個包進行更改或者重新編譯,所有引用了這個包的客戶端程式都必須全部重新編譯

Go中的包模型採用了顯示依賴關係的機制來達到快速編譯的目錄。編譯器會從字尾名為.go的物件檔案(需要且只需要這個檔案)中提取傳遞依賴關係型的資訊

如果A.go 依賴B.go,而B.go 又依賴C.go:

  • 編譯C.go,B.go,然後是A.go
  • 為了編譯A.go ,編譯器讀取的是B.go,而不是C.go

這種機制對於編譯大型的專案時可以顯著提升編譯速度


示例

在目錄example3 下,有目錄cat 和main 。 在 cat 目錄下有cat.go檔案。 在main目錄下有main.go檔案

//cat.go 檔案
package cat

import "fmt"

var Name string = "Tom"
var Age int = 5

//初始化函式
func init() {
	fmt.Println("this is cat package")
	fmt.Println("init 函式修改前", Name, Age)
	Name = "jack"
	Age = 3
	fmt.Println("init 函式修改後", Name, Age)
}

//main.go檔案
package main

import (
	"dev_code/day9/example3/cat"
	"fmt"
)

//呼叫其他包,程式載入順序   cat.go中全域性變數-->cat.go中的init()函式--->main.go中的main()函式
func main() {
	fmt.Println("貓的名字:", cat.Name)
	fmt.Println("貓的年齡:", cat.Age)
}

//執行main.go檔案 輸出結果:
this is cat package
init 函式修改前 Tom 5
init 函式修改後 jack 3
貓的名字: jack
貓的年齡: 3


程式執行順序

Go程式 的執行(程式啟動)順序如下:

  1. 按順序匯入所有被main包引用的其他包,然後在每個包中執行如下流程
  2. 如果該包又匯入了其他包,則從第一部開始遞迴執行,但是每個包只會被匯入一次
  3. 然後一相反的順序在每個包中初始化常量和變數,如果該包含有init 函式的話,則呼叫該函式。
  4. 在完成這一切後,main也執行同樣的過程。最後呼叫執行程式

在example5 目錄下有demo包,main包,test包。 在demo包中有demo.go檔案。在main包中有main.go檔案。在test包中有test.go檔案

//demo.go檔案
package demo

import "fmt"

var Name string = "this is demo package "
var Age int = 20

func init() {
	fmt.Println("this is demo init()")
	fmt.Println("demo.package.Nam:", Name)
	fmt.Println("demo.package.Age:", Age)
	Name = "this is demo New"
	Age = 200
	fmt.Println("demo.package.Nam:", Name)
	fmt.Println("demo.package.Age:", Age)
}

//test.go檔案
package test

import (
  // 在引用的包前面加上 _  表示只加載這個包,但是不進行引用包裡的函式和變數
	_ "dev_code/day9/example4/demo"
	"fmt"
)

var Name string = "this is test package"
var Age int = 10

func init() {
	fmt.Println("this is test init()")
	fmt.Println("test.package.Nam:", Name)
	fmt.Println("test.package.Age:", Age)
	Name = "this is test New"
	Age = 100
	fmt.Println("test.package.Nam:", Name)
	fmt.Println("test.package.Age:", Age)
}

//main.go檔案
package main

import (
	"dev_code/day9/example4/test"
	"fmt"
)

func main() {
	//main --->test--->demo
	fmt.Println("main.package", test.Name)
	fmt.Println("main.package", test.Age)
}


//執行main.go檔案輸出結果:
this is demo init()
demo.package.Nam: this is demo package 
demo.package.Age: 20
demo.package.Nam: this is demo New
demo.package.Age: 200
this is test init()
test.package.Nam: this is test package
test.package.Age: 10
test.package.Nam: this is test New
test.package.Age: 100
main.package this is test New
main.package 100

匯入包時空白識別符號的作用

如果匯入了一個包,卻沒由使用它,則會在構建時引發錯誤,如imported andnot used

所以,我們可以使用空白識別符號_ 來解決


方法一:

宣告一個全域性空白識別符號(在main()函式之前),該識別符號從 未使用的包中訪問符號。

package main

import "os"

var _ = os.Open

func main() {
}


方法二:

在未使用的包前加上一個空白識別符號。只初始化載入該包,而不去使用該包的函式和變數

package main

import _ "os"

func main() {
}


包的別名

在不同的父目錄下,存在相同名字的包。比如,在example4和example5目錄下,都有cat 包。那麼,不管是匯入,還是使用包裡的函式或者變數,都很不方便,容易混淆。

此時我們可以在匯入包的時候,在前面加上包的別名,在使用的使用,使用別名呼叫即可

package main
//匯入fmt 包,同時,設定a 為fmt 包的別名
import a "fmt"

func main() {
  //在使用時,使用別名進行呼叫
	a.Println("通過包的別名進行呼叫")
}

//輸出結果:
通過包的別名進行呼叫