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

2021-01-07 51CTO

 前言

Hey,大家好呀,我是星期八,咱們原來寫的代碼,都是縮在一塊的,久而久之咱們可能都能感覺到冗餘。

所以今天就來學一下包這個東西,將咱們的代碼拆分一下。

包可以理解為存放多個.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中可見性很簡單不管是變量還是函數還是結構體。

首字母大寫在哪都能訪問。

首字母小寫只能在當前包使用。

示例

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方法

其實每次導入其他包的時候都會執行包的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方法比main方法更提前一步執行。

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

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


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

先看一下執行結果


執行結果是inner的init方法先執行然後是ohter的init方法。

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

它的圖應該是這樣子的。


意思是main導入了ohter那就執行other的init方法。

但是在導入ohter時發現other導入了inner那就執行inner的init方法。

總結

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

可能有點不太好理解,但是還是要堅持,一定要多敲兩次。

【編輯推薦】

【責任編輯:

姜華

TEL:(010)68476606】

點讚 0

相關焦點

  • 小試牛刀,手把手帶你實現第一個Go程序
    上篇文章,我們已經搭建了Go語言環境,可以戳這裡:手把手帶你進行Golang環境配置,本次我們來安排一下如何在win平臺上輸出都一個Go程序。在Goland的代碼界面,點擊右鍵,運行:go build命令上述,我們通過右擊 run main.go 成功的運行了項目,但是go是靜態編譯語言,可以直接編譯成xx.exe發給別人使用。cmd切換到項目目錄下:
  • 一篇文章教會你如何使用Go語言Modules
    go moudules是Go的一個包管理工具,官方提供的,還是比較靠譜的,最低Go版本要求1.11+。可以理解為Python的虛擬環境,或者Java的maven,PHP的composer。其本質解決的問題就是包管理混亂問題。反正就是,用就完事了,只有好事,沒有壞事。
  • Go 語言設計哲學之十三:理解包導入路徑的含義
    與C 語言的頭文件包含機制相比則是「先進」了許多。即便是每次編譯都是從頭開始。避免了 C 語言那種通過頭文件分析依賴的巨大開銷。Go 語言以包為基本構建單元的構建模型,依賴分析非常簡單。這樣,Go編譯器在編譯某包M時,針對M依賴的每個包導入(比如:導入包N),只需讀取一個目標文件即可(比如:N包編譯成的目標文件,該目標文件中已經包含了N包的依賴包的導出信息),而無需再讀取其他文件中的信息了。通過 package 關鍵字聲明 Go 源文件所屬的包: 上述源碼表示:文件 xx.go 是包 x 的一部分。
  • 你「理解」英語的語言必須是英語:Here you go
    你「理解」英語的語言必須是英語:Here you go學習英語就是為了「用」。什麼時候「用」?你把學過的英語用起來理解英語是就是「在用」英語。在大家基本都缺乏英語「使用語言環境」的現實裡,用英語理解讀懂英語就是一個人最能夠有機會「用」英語的時候。Here you go什麼意思?不要去問「中文什麼意思?」,問「英語什麼意思?」
  • 【零基礎入門】手把手帶你系統化學習R語言
    如果說有一門簡單易學、通俗易懂並且集上述功能為一體的程式語言讓科研人員從中解脫出來,R語言當仁不讓。 R語言是一款免費開源軟體,其提供了超過12000個R包,幾乎所有類型的數據分析任務都可以在R中完成。
  • 手把手教會你!
    手把手教會你! 總有小夥伴在畫畫的時候被「手」卡住,俗話說:「畫馬難畫走,畫人難畫手」,畫手真的很考驗一個畫師功力。好看的手有力而形象,可以給整幅畫作添上亮點,而畫得不好的手呢,就容易把畫面整體的風格打破。因此,今天微課菌就來分享一組,畫手的教程,很詳細很具體,相信你看完肯定能學會!
  • 深入理解 Go 語言 defer
    defer 估計是每個 Gopher 每天寫代碼都會寫,那麼你是不是真正的理解了 defer 呢?不妨看一下下面這個代碼片段,這個是我之前給 UC 那邊一個 team 做 Golang 培訓的時候想的例子。
  • GO語言入門(第一個go程序)
    作為一門具有明確編碼規範的語言,它要求可以採用不同的編譯器如 gc 和 gccgo(第 2.1 節)進行編譯工作,這對語言本身擁有更好的編碼規範起到很大幫助。LALR 是 Go 語言的語法標準,你也可以在 src/cmd/internal/gc/go.y 中查看到,這種語法標準在編譯時不需要符號表來協助解析。
  • Go語言中 Unsafe 的用法
    如果你對這個話題想做更深入的了解,我推薦你閱讀另外一篇文章 Cast and Conversion with Go (https://medium.com/a-journey-with-go/go-cast-vs-conversion-by-example-26e0ef3003f0)Go 1 compatibility guidelines
  • 大話go 語言:談談 go 語言的類型系統
    go 語言就擇優而選,並且索性做徹底,對於沒有用到的變量直接編譯錯誤,對於導入的沒用的包也直接提示錯誤變量在前,類型在後。這也是很多人不習慣的,但 go 並不是第一個。這樣也有個好處,方便編譯器處理,對於 C語言指針的弊端也有了統一的處理。
  • 在家包粽子,不漏米才重要,捆繩你知道怎麼處理嗎,手把手教會你
    在家包粽子,不漏米才重要,捆繩你知道怎麼處理嗎,手把手教會你!自從來美國後,每逢端午我一定會包肉粽,除了愛過節的儀式感,每到傳統節慶時,海外遊子的思鄉情懷必會大噴發,看著媒體的各種過節美食大放送,再回頭看看自己佇立的美食沙漠,突然覺得仿佛身處平行時空,巨大的悲傷馬上如海嘯般襲來,我哭!
  • [GO語言基礎] 一.為什麼我要學習Golang以及GO語言入門普及
    學習體驗也十分順暢,不得不說,Go 是一種經過精心設計的實用性語言。舉個例子:一旦你知悉了 Go 的語法,就能將其他語言中慣用法延續到 Go 中。只要你學會一些 Go,就可以相對輕易地推測 Go 語言的其他特性。憑藉一些來自其他語言的知識,我能夠閱讀並理解 Go 代碼,而不需要過多的搜索(Google)。與 C/C++、Java、Python 等相比,Go 並沒有那麼多痛點,而且更具生產力。
  • 星巴克298一盒的美式摩卡乳酪月餅,自己做多實惠,手把手教會你
    星巴克298一盒的美式摩卡乳酪月餅,自己做多實惠,手把手教會你街上琳琅滿目的月餅,你最愛哪一款?這款月餅,我給它分為了3層,摩卡月餅皮,椰蓉奶酪餡,藍莓內心,吃起來口感非常豐富,酸酸甜甜的藍莓餡,奶香濃鬱的乳酪餡,苦中帶甜的摩卡月餅皮,咬上一口不覺得甜膩,反而多種味道在舌尖盤旋,滿滿地幸福感。大家可能會覺得,這月餅我自己在家怎麼能做呢,其實做過的朋友都成功了,我手把手教你,你還怕什麼?肯定一次成功!只要你跟著步驟做就可以,不會的地方隨時可以艾特我。
  • 60分鐘快速了解Go語言
    import ("fmt" // Go語言標準庫中的包"io/ioutil" // 包含一些輸入輸出函數m "math" // 數學標準庫,在此文件中別名為m"net/http" // 一個web伺服器包"os" // 系統底層函數,如文件讀寫"strconv" /
  • sexp:連接R語言與Go的工具包
    辦公室中用於此項工作的最常用工具是R,但就內存或計算時間而言,它不能很好地擴展。我開始嘗試通過並行化解決這個問題,但R只能很好地處理令人尷尬的並行計算。即使這樣,R的並行包也可能非常笨重,並且經常導致內存膨脹。尋找一種可擴展的語言,我開始在Go中進行大量的數據分析,基於聲譽及其高度明確的語法和錯誤處理。
  • Go語言常見語法錯誤
    如果你真的需要引入的包,你可以添加一個"_"下劃線標記符,來作為這個包的名字,從而避免編譯失敗。下滑線標記符用於引入,但不使用。/main.go:3:1: syntax error: non-declaration statement outside function body正確代碼:package mainvar myvar = 1func main() {}5、使用簡式聲明重複聲明變量你不能在一個單獨的聲明中重複聲明一個變量
  • 一篇文章帶你入門Go語言基礎之並發
    引言Go語言,專門為並發而生的語言,每啟動一個微線程創建一個代價大概2KB起步假設一個內存條大小4G,一個微線程2kb,1G=1024M=1048576kb,1048576/2=524288,五十多萬個但是你知道像Java,Python等語言,一個線程代價多大嗎???
  • Go語言錯誤總結(一)
    Go語言錯誤總結(一)1、開大括號不能放在單獨的一行在大多數其他使用大括號的語言中
  • Go語言defer你不知道的事
    Go 語言中的 defer 語句用於延遲函數的調用
  • 解讀 Go 語言的 2019:Go 語言不行了嗎?
    此外,還有大名鼎鼎的 Kubernetes 及其生態圈中的那些知名項目。更多的優秀 Go 語言項目可以參考我在極客時間專欄《Go 語言核心 36 講》中的思維導圖。如果你只是想知道國內的 Go 程序開發者都發布了哪些開源項目,那麼也可以參考我發起的 awesome-go-China 項目。另一方面,對於那些面向企業的管理系統,Go 語言更是不在話下。