首頁  >  文章  >  後端開發  >  手把手教你去理解Go語言中的包

手把手教你去理解Go語言中的包

Go语言进阶学习
Go语言进阶学习轉載
2023-07-21 13:07:131381瀏覽

套件

#套件可以理解為存放多個 .go的資料夾但是這個資料夾下面的第一行的package後面跟的不再是main了而是檔案名,就像這樣。

目錄

手把手教你去理解Go語言中的包

#clacmain.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()
}

執行結果

手把手教你去理解Go語言中的包

#可以看到在#main.go中成功呼叫了clac套件中的程式碼。


註:匯入套件只需要匯入到資料夾即可就可以呼叫下面所有的方法和屬性不再需要套件名稱.xx.go這種方式。

如上述導入calc#不管calc下面有幾個.go檔案裡面的方法和屬性都可以隨便呼叫。


导入包注意事项

上述我是直接通过

import (
   "a3_course/clac"
)

这种方式导入包的但是在你们那可能不太行。

因为我使用的是go mod所以通过项目目录/包名导入。

手把手教你去理解Go語言中的包

如果你没有使用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
}

访问私有变量报错信息。

手把手教你去理解Go語言中的包


结构体可见性的问题

我们知道结构体是有字段的但是你想过结构体的字段大小写问题吗?

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)
}

执行结果

手把手教你去理解Go語言中的包

会发现执行结果少了一个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()
}

执行结果

手把手教你去理解Go語言中的包


匿名导入包

匿名导入包就是相当于不用这个包里面的东西。

可能有人就会问了那不用包里面的东西,那还导入作甚呢?

嗯...这个匿名导入包主要要跟包的一个init方法有关系咱们先继续看。

匿名导入包示例代码

package main


//前面有个 _ 就表示是匿名导入
import _ "a3_course/clac"


func main() {


}


包的init方法

其实每次导入其他包的时候都会执行包的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() {


}

执行结果

手把手教你去理解Go語言中的包

可以發現我雖然是匿名導入包但是仍然還是執行了add.go# sub.go下的init方法。

這就說明了一個問題導入一個套件會執行這個套件下面的所有##init##方法不管下面有幾個.go檔。

註:套件的#init方法不能寫參數也不能有回傳值init方法只能在導入時呼叫不能主動呼叫。

init#方法比main#方法更提前一步執行


多個包嵌套導入時init方法執行的順序

程式碼較多就直接如圖所示了:

手把手教你去理解Go語言中的包

這意思是main.go導入了other套件other套件導入了inner包,娃娃。

先看一下執行結果

手把手教你去理解Go語言中的包

#

執行結果是innerinit方法先執行然後​​是ohter#init方法。

其實本質是碰到import就執行被導入包的init方法。

它的圖應該是這樣子的。

手把手教你去理解Go語言中的包

#

意思是main導入了ohter那就執行otherinit方法。

但在匯入ohterother導入了inner那就執行innerinit方法。


總結

上述我們學習了Go基礎之包,學習如何##建立套件 #,組織套件#匯入套件的注意事項套件的權限問題(大寫開頭所有可見)##「匿名導入套件## ,init方法

####多個init方法#########注意事項。 ##########

以上是手把手教你去理解Go語言中的包的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:Go语言进阶学习。如有侵權,請聯絡admin@php.cn刪除