go包的理解

結論:node

  1. import時指定的字符串,是相對於$GOPATH的目錄路徑,告訴了go,要去加載這個目錄下全部的包文件(不包括子目錄中的文件)
  2. 一個目錄中全部的源文件(不包括子目錄)表明了單獨的一個包,這些源文件內的package關鍵字指出的包名,必須一致,不然沒法被使用
  3. import指定的加載目錄、目錄中的源文件名字、源文件內經過package關鍵字指定的包名。這三者能夠不同。導入後,根據package指定的包名,來使用包中的導出成員。
  4. 導入兩個目錄,這兩個目錄中的源文件內指定的包名,若是出現相同,則導入目錄時會失敗
  5. 同一個包,間接或直接被導入屢次。這個包只會被初始化一次。如init執行一次,包級別變量的內存只會被分配一次,後續要使用的話,則繼續使用上次分配時的值。(這個規律和nodejs也是一致的)這也就是爲何使用mysql時,要導入兩個包:
    1. import "database/sql" import _ "github.com/go-sql-driver/mysql"
    2.  第二個包中引用了第一個包,init函數中對第一個包裏的數據進行了一些mysql相關的操做。使後續直接使用第一個包時,能關聯得上mysql。
    3. 導入第二個包僅僅是爲了執行裏面的init函數,從而影響第一個包的行爲。因此第二個包空導入便可
  6. 當源文件被加載時,文件內的init函數會被自動執行:
    1. 經過import來加載一個目錄時,若是這個目錄中有多個源文件,則這些源文件中的init函數都會執行,但文件之間的init函數的執行次序不肯定,看go加載文件是的順序
    2. 一個源文件內能夠定義多個init函數,多個init函數會按順序從上往下執行。雖然一個文件內能夠定義多個init,可是沒有這個必要,把邏輯都集中在一個init函數中,效果同樣

測試1

$GOPATH目錄以下:mysql

├─pkg
└─src
  └─app.go
  └─m1
    └─k1.gogit

app.go:github

package main

import "m1"

func main() {
    x1.Show()
}

 k1.go:sql

package x1

import "fmt"

func Show(){
    fmt.Println("show call")
}

 運行app.go:輸出 show call。app

測試2

在以上的m1目錄中,建立一個文件k2.go函數

package x2

import "fmt"

func Show(){
    fmt.Println("show call")
}

運行app.go提示:app.go:3:8: found packages x1 (k1.go) and x2 (k2.go) in D:\GoPath\src\m1測試

測試3

k1和k2文件中,都經過package指定包名爲x1。app.go中導入這兩個目錄,運行報錯:spa

.\app.go:4:8: x1 redeclared as imported package name
previous declaration at .\app.go:3:8
.\app.go:7:2: undefined: "m2".FnInK13d

 解決辦法:導入的時候,將衝突的包名,重命名爲另外一個值便可,如如下k2pkg

 測試4

k1.go:

package x1

import "fmt"

var x1Data int = 1;

func init(){
    fmt.Println("x1 init call")
    x1Data = 2;
}

func ShowData(){
    fmt.Println(x1Data)
}

func SetData(x int){
    x1Data = x;
}

k2.go:

package x2

import "m1"
import "fmt"

func init(){
    fmt.Println("x2 init call")
    x1.SetData(333)
}

app.go:

package main

import _ "m2"
import "m1"

func main() {
    x1.ShowData()
}

> go run app.gox1 init callx2 init call333

相關文章
相關標籤/搜索