#套件可以理解為存放多個 .go
的資料夾但是這個資料夾下面的第一行的package
後面跟的不再是main
了而是檔案名,就像這樣。
#clac
和main.go
檔案是同級的。
可以看到clac
資料夾下的add.go
#第一行不再是main
而是資料夾名稱clac
同理sub.go
#第一行也是。
這個只是單獨的解釋套件的定義方式沒有實際意義。
如果這個資料夾要當套件使用資料夾名稱中不能包含_
。
上面我們知道了套件是如何定義的。
並且在和main.go
#同級的專案目錄下建了一個 #clac
#。
在clac
套件下有兩個檔案一個是add .go
一個是sub.go
#兩個資料夾分別都有對應的方法。 問題來了? ? ?
那我們如何在main.go
#中使用上述建立的套件呼叫裡面的方法呢?
這就是要導入它們了。
範例程式碼
#package main import ( "a3_course/clac" ) func main() { clac.Add() clac.Sub() }
執行結果
#可以看到在#main.go
中成功呼叫了clac
套件中的程式碼。
註:匯入套件只需要匯入到資料夾即可就可以呼叫下面所有的方法和屬性不再需要套件名稱.xx.go
這種方式。
如上述導入calc
#不管calc
下面有幾個.go
檔案裡面的方法和屬性都可以隨便呼叫。
上述我是直接通过
import ( "a3_course/clac" )
这种方式导入包的但是在你们那可能不太行。
因为我使用的是go mod
所以通过项目目录/包名
导入。
如果你没有使用go mod
是传统的方式那么导入包需要从GOPATH/src
进行导入这里不举例了。
如果还不会使用go mod
记得爬楼看以往文章,上面有教程,一篇文章教会你如何使用Go语言Modules,记得要拥抱未来噢。
可见性在其他语言中有的叫私有成员之类的称呼在Go中就叫可见性。
Go中可见性很简单不管是变量还是函数还是结构体。
首字母大写在哪都能访问。
首字母小写只能在当前包使用。
示例
clac/add.go
文件
package clac import ( "fmt" ) //这是一个公开的变量 var Name = "张三" //这是一个私有变量,只能在 clac 包中访问 var age = 18 //这是一个公开的函数 func Add() { fmt.Println("我是做加法的...") }
main.go
文件
func main() { clac.Add() clac.Sub() fmt.Println(clac.Name) //clac中的age是小写开头,属于私有变量,所以其他包不能访问 //fmt.Println(clac.age) // cannot refer to unexported name clac.age }
访问私有变量报错信息。
我们知道结构体是有字段的但是你想过结构体的字段大小写问题吗?
type Student struct { Name string age int } //age是小写开头
结构体名开头是不是大写影响的主要是在其他包里面的调用权限问题。
结构体字段开头是不是大写主要影响的是调用里面字段的问题一个明显的问题就是序列化。
更多结构体的相关文章,可前往:Go语言基础之结构体(春日篇)
示例代码
package main import ( "encoding/json" "fmt" ) type Student struct { Name string age int } func main() { var s1 = Student{ Name: "张三", age: 18, } serializeBytes,err:=json.Marshal(s1) if err != nil { fmt.Println("序列化失败") } serializeStr := string(serializeBytes) fmt.Println(serializeStr) }
执行结果
会发现执行结果少了一个age
。
这是因为age
小写开头属于私有变量。
但是json.Marshal(s1)
这个已经属于其他包了所以访问不到age
。
我们在导入包时其实还可以自定义包名就像Python中的 from xx import xx as yy
。
示例代码
package main //给 clac 包起别名 import cl "a3_course/clac" func main() { cl.Add() }
执行结果
匿名导入包就是相当于不用这个包里面的东西。
可能有人就会问了那不用包里面的东西,那还导入作甚呢?
嗯...这个匿名导入包主要要跟包的一个init
方法有关系咱们先继续看。
匿名导入包示例代码
package main //前面有个 _ 就表示是匿名导入 import _ "a3_course/clac" func main() { }
其实每次导入其他包的时候都会执行包的init
方法。
示例
//clac/add.go package clac import "fmt" func init() { fmt.Println("clac/add.go/init") } func Sub() { fmt.Println("我是做减法的...") } //clac/sub.go package clac import "fmt" func init() { fmt.Println("clac/sub.go/init") } func Sub() { fmt.Println("我是做减法的...") }
main.go
package main import _ "a3_course/clac" func main() { }
执行结果
可以發現我雖然是匿名導入包但是仍然還是執行了add.go
和# sub.go
下的init
方法。
這就說明了一個問題導入一個套件會執行這個套件下面的所有##init##方法不管下面有幾個.go
檔。
註:套件的#init方法不能寫參數也不能有回傳值init
方法只能在導入時呼叫不能主動呼叫。
init 程式碼較多就直接如圖所示了: 這意思是 先看一下執行結果 執行結果是 其實本質是碰到 它的圖應該是這樣子的。 意思是 但在匯入 上述我們學習了Go基礎之包,學習如何##建立套件 #,組織套件,#匯入套件的注意事項。 套件的權限問題(大寫開頭所有可見),##「匿名導入套件## ,init方法,#方法比main
#方法更提前一步執行。
多個包嵌套導入時init方法執行的順序
main.go
導入了other
套件other
套件導入了inner
包,娃娃。 inner
的init
方法先執行然後是ohter
的#init
方法。 import
就執行被導入包的init
方法。 main
導入了ohter
那就執行other
的init
方法。 ohter
other
導入了inner
那就執行inner
的init
方法。 總結
以上是手把手教你去理解Go語言中的包的詳細內容。更多資訊請關注PHP中文網其他相關文章!