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("通過包的別名進行呼叫") } //輸出結果: 通過包的別名進行呼叫