<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 語言基礎(chǔ)-包

          共 10861字,需瀏覽 22分鐘

           ·

          2022-07-06 12:44

          點擊上方“Go語言進階學(xué)習(xí)”,進行關(guān)注

          回復(fù)“Go語言”即可獲贈從入門到進階共10本電子書

          新知遭薄俗,舊好隔良緣。

          你好,我是四哥。

          上一篇文章我們學(xué)習(xí)了函數(shù),這篇文章我們再來學(xué)習(xí)寫包的用法。

          什么是包以及為什么我們要使用它?

          到目前為止,我們看到的 Go 程序只有一個文件,其中包含一個 main 函數(shù)和幾個其他函數(shù)。在實際業(yè)務(wù)開發(fā)時,這種將所有源代碼寫入單個文件的方法是不可擴展的。這種代碼的重用性和可維護性將變得不可能,這個時候包就可以派上用場了。

          包是位于同一目錄中的 .go 結(jié)尾的文件的集合,用來組織源代碼,實現(xiàn)更好的可重用性和可讀性。包提供了代碼劃分,使得維護 Go 項目更加容易。

          例如,假設(shè)我們正在用 Go 編寫一個金融系統(tǒng),包含如下功能:簡單的利息計算、復(fù)利計算和貸款計算等。組織這個系統(tǒng)的的一個簡單辦法就是按照功能劃分,我們可以創(chuàng)建三個包 simpleinterest、compoundinterest 和 loan。如果 loan 包需要用到 simpleinterest 包的功能,只需要簡單導(dǎo)入 simpleinterest 包即可,這樣代碼就實現(xiàn)重用了。

          我們將通過創(chuàng)建一個簡單的應(yīng)用程序來學(xué)習(xí)包,用于計算給定本金、利率和時間的情況下利息是多少。

          main 函數(shù)和 main 包

          每個可執(zhí)行的 Go 應(yīng)用程序都必須包含 main 函數(shù)。該函數(shù)是程序執(zhí)行的入口,主要功能應(yīng)該在 main 包內(nèi)。

          package packagename

          上面的語法用于指定源文件屬于 packagename 包,通常出現(xiàn)在文件的第一行。

          讓我們開始為我們的應(yīng)用程序創(chuàng)建 main 函數(shù)和 main 包。

          運行下面命令,在當前用戶的 Documents 目錄中創(chuàng)建一個名為 learnpackage 的目錄。

          mkdir ~/Documents/learnpackage/

          在 learnpackage 目錄中創(chuàng)建一個名為 main.go 的文件,其中包含以下代碼:

          package main

          import "fmt"

          func main() {
              fmt.Println("Simple interest calculation")
          }

          package main 代碼用于指定該文件屬于主包;

          import "packagename" 語句用于導(dǎo)入已存在的包;

          packagename.FunctionName() 是調(diào)用包中函數(shù);

          上面代碼的第 3 行,我們導(dǎo)入 fmt 包以便能調(diào)用包里的 Println() 函數(shù),fmt 是 Go 語言標準庫中內(nèi)置的一個包。主函數(shù)會打印 Simple interest calculation。

          cd 到 learnpackage 目錄并且編譯上面的代碼

          cd ~/Documents/learnpackage/
          go install

          如果一切順利,二進制文件將被編譯并可以執(zhí)行。在終端中鍵入命令 learnpackage,將會看到如下輸出:

          Simple interest calculation

          Go Module

          我們將會這樣構(gòu)建代碼,與計算利息相關(guān)的功能函數(shù)都放在 simpleinterest 包里。為此,我們需要創(chuàng)建一個自定義包 simpleinterest,其中包含計算利息的函數(shù)。在創(chuàng)建自定義包之前,我們需要先了解 Go Modules,創(chuàng)建自定義包需要 Go Modules。

          簡單來說,Go Module 只不過是 Go 包的集合。你可能會有疑問,為什么我們需要 Go 模塊來創(chuàng)建自定義包呢?答案是我們創(chuàng)建的自定義包的導(dǎo)入路徑來源于 go 模塊的名稱。除此之外,我們的應(yīng)用程序使用的所有其他第三方包(例如來自 github 的源代碼)將與版本一起出現(xiàn)在 go.mod 文件中。當我們創(chuàng)建一個新模塊時,會創(chuàng)建出一個 go.mod 文件,下一小節(jié)會講到這點。

          可能你又會疑惑了:為什么到現(xiàn)在我們還沒有創(chuàng)建 Go 模塊程序也能執(zhí)行成功?答案是,本系列教程到目前為止,我們從未創(chuàng)建過自定義包,因此不需要 Go 模塊。

          理論知識學(xué)完了,讓我們來創(chuàng)建自己的 Go 模塊和自定義包。

          創(chuàng)建 Go module

          執(zhí)行下面命令確保在 learnpackage 目錄下,

          cd ~/Documents/learnpackage/

          在該目錄下輸入如下命令創(chuàng)建名為 learnpackage 的 go 模塊。

          go mod init learnpackage

          上面的命令將創(chuàng)建一個名為 go.mod 的文件,下面是該文件的內(nèi)容:

          module learnpackage

          go 1.13

          代碼行 module learnpackage 指定模塊的名字為 learnpackage。正如之前提到的,learnpackage 是模塊的基礎(chǔ)路徑,想要導(dǎo)入模塊的任何一個包必須基于此路徑。最后一行指定此模塊中的文件使用 1.13 的 go 版本。

          創(chuàng)建一個自定義包:計算利息

          屬于一個包的源文件應(yīng)該放在它們自己的單獨文件夾中。Go 中的約定是文件夾名稱與包名相同。

          讓我們在 learnpackage 文件夾中創(chuàng)建一個名為 simpleinterest 的文件夾。mkdir simpleinterest 將會創(chuàng)建該文件夾。

          simpleinterest 文件夾中的所有文件都應(yīng)該以 package simpleinterest 開頭,因為它們都屬于 simpleinterest 包。

          在 simpleinterest 文件夾中創(chuàng)建一個文件 simpleinterest.go。

          下面是程序的結(jié)構(gòu)目錄:

          ├── learnpackage
          │   ├── go.mod
          │   ├── main.go
          │   └── simpleinterest
          │       └── simpleinterest.go

          將以下代碼添加到 simpleinterest.go 文件中。

          package simpleinterest

          //Calculate calculates and returns the simple interest for a principal p, rate of interest r for time duration t years
          func Calculate(p float64, r float64, t float64) float64 {
              interest := p * (r / 100) * t
              return interest
          }

          在上面的代碼中,我們創(chuàng)建了一個計算并返回利息的函數(shù) Calculate()。

          導(dǎo)入自定義包

          要使用自定義包,我們必須先導(dǎo)入它。導(dǎo)入路徑是模塊名加上包的子目錄和包名。在我們的例子中,模塊名稱是 learnpackage,包 simpleinterest 位于 learnpackage 下的 simpleinterest 文件夾中。

          ├── learnpackage
          │   └── simpleinterest

          所以 import "learnpackage/simpleinterest" 代碼將導(dǎo)入 simpleinterest 包。

          如果我們的目錄結(jié)構(gòu)是這樣的:

          learnpackage
          │   └── finance
          │       └── simpleinterest

          那么導(dǎo)入包的語句將會是 mport "learnpackage/finance/simpleinterest"。

          將下面的代碼加入 main.go

          package main

          import (
              "fmt"
              "learnpackage/simpleinterest"
          )

          func main() {
              fmt.Println("Simple interest calculation")
              p := 5000.0
              r := 10.0
              t := 1.0
              si := simpleinterest.Calculate(p, r, t)
              fmt.Println("Simple interest is", si)
          }

          上面的代碼導(dǎo)入了 simpleinterest 包并使用了 Calculate() 函數(shù)來計算利息。標準庫中的包不需要模塊名稱前綴,比如直接導(dǎo)入 fmt 包也是可以的。執(zhí)行代碼輸出:

          Simple interest calculation
          Simple interest is 500

          關(guān)于 go install 更多的知識

          現(xiàn)在我們了解了包的工作原理,是時候來討論關(guān)于 go install 的用法了。像 go install 這樣的 Go 工具在當前目錄的上下文中工作。我們來理解是什么意思,到目前為止,我們一直在目錄 ~/Documents/learnpackage/ 中運行 go install。如果我們嘗試在其他任何目錄執(zhí)行這個命令,將會報錯。

          嘗試執(zhí)行命令 cd ~/Documents/ 然后運行 go install learnpackage,它將失敗并出現(xiàn)以下錯誤:

          can't load package: package learnpackage: cannot find package "learnpackage" in any of:
              /usr/local/Cellar/go/1.13.7/libexec/src/learnpackage (from $GOROOT)
              /Users/nramanathan/go/src/learnpackage (from $GOPATH)

          我們一起來分析下錯誤的原因,go install 需要一個可選的包名作為參數(shù)(在我們的例子中包名是 learnpackage),如果執(zhí)行命令的當前目錄或者其父級目錄下存在這個包,它會嘗試編譯 main 函數(shù)。

          我們在 Documents 目錄中沒有 go.mod 文件,因此 go install 會提示找不到包 learnpackage。

          當我們 cd 到 ~/Documents/learnpackage/ 目錄時,該目錄下存在 go.mod 文件,該文件中指定了模塊名稱 learnpackage。

          所以 go install learnpackage 將在 ~/Documents/learnpackage/ 目錄中工作。

          但是到目前為止,我們只是在使用 go install 并且沒有指定包名。如果沒有指定包名,go install 將默認為當前工作目錄中的模塊名,這就是我們沒有指定包名但仍然能執(zhí)行成功的原因。因此,在 ~/Documents/learnpackage/ 目錄下執(zhí)行下面 3 個命令是等效的:

          go install

          go install .

          go install learnpackage

          上面我們提到 go install 能夠遞歸地在父目錄中搜索 go.mod 文件,讓我們檢查一下這點是否正確。

          cd ~/Documents/learnpackage/simpleinterest/

          執(zhí)行上面的命令 cd 到 simpleinterest 目錄,在該目錄下執(zhí)行下面的命令:

          go install learnpackage

          Go install 將能在父目錄 learnpackage 中找到一個 go.mod 文件,該文件定義了模塊 learnpackage,因此它可以工作。

          可導(dǎo)出

          simpleinterest 包里的 Calculate() 函數(shù)開頭字母是大寫的。這在 Go 中有特別的定義,任何以大寫字母開頭的變量或函數(shù)都是可導(dǎo)出。只能訪問其他包中可導(dǎo)出的變量或者函數(shù),在我們這個例子中,我們能在 main 包里訪問 Calculate() 函數(shù),因為它是可導(dǎo)出的。

          如果將 Calculate() 函數(shù)開頭字母小寫 calculate(),再次嘗試從 main 包訪問,將會報錯:

          # learnpackage
          ./main.go:13:8: cannot refer to unexported name simpleinterest.calculate
          ./main.go:13:8: undefined: simpleinterest.calculate

          因此,如果你想從其他包能訪問包內(nèi)的函數(shù),則應(yīng)將其首字母大寫。

          init 函數(shù)

          Go 里每個包都可以包含一個 init() 函數(shù)。init() 函數(shù)不能有任何返回值,也不能有任何參數(shù)。在代碼中不能顯式地調(diào)用 init() 函數(shù),包初始化時會自動調(diào)用 init() 函數(shù)。init() 函數(shù)語法如下:

          func init() {
          }

          init() 函數(shù)可以用于執(zhí)行初始化任務(wù),也可用于程序運行前一些參數(shù)的驗證。

          包的初始化順序如下:

          1.首先初始化包級別的變量;2.接著會調(diào)用 init() 函數(shù),一個包可以有多個 init() 函數(shù)(在單個文件中或分布在多個文件中),它們按照呈現(xiàn)給編譯器的順序被調(diào)用;

          如果一個包導(dǎo)入其他包,則首先初始化導(dǎo)入的包。

          一個包即使被多個包導(dǎo)入,也只會被初始化一次。

          我們對之前的程序做一些修改,以便能更好地學(xué)習(xí)了解 init() 函數(shù)。

          首先,讓我們將 init 函數(shù)添加到 simpleinterest.go 文件中。

          package simpleinterest

          import "fmt"

          /*
           * init function added
           */

          func init() {
              fmt.Println("Simple interest package initialized")
          }
          //Calculate calculates and returns the simple interest for principal p, rate of interest r for time duration t years
          func Calculate(p float64, r float64, t float64) float64 {
              interest := p * (r / 100) * t
              return interest
          }

          上面的代碼添加了一個簡單的 init 函數(shù),它只負責(zé)打印 Simple interest package initialized。

          現(xiàn)在,我們來修改下 main 包,我們都知道計算利息時本金、利率和時間都應(yīng)該大于零,我們將在 main.go 文件里定義包級別的變量并且在 init() 函數(shù)校驗這些變量。

          main.go 文件如下:

          package main

          import (
              "fmt"
              "learnpackage/simpleinterest" //importing custom package
              "log"
          )
          var p, r, t = 5000.010.01.0

          /*
          * init function to check if p, r and t are greater than zero
           */

          func init() {
              println("Main package initialized")
              if p < 0 {
                  log.Fatal("Principal is less than zero")
              }
              if r < 0 {
                  log.Fatal("Rate of interest is less than zero")
              }
              if t < 0 {
                  log.Fatal("Duration is less than zero")
              }
          }

          func main() {
              fmt.Println("Simple interest calculation")
              si := simpleinterest.Calculate(p, r, t)
              fmt.Println("Simple interest is", si)
          }

          main.go 修改如下:

          1.p、r 和 t 變量從主函數(shù)級別移至包級別。2.添加了一個 init() 函數(shù),如果本金、利率或時間有一個小于 0,log.Fatal() 會打印日志并終止程序。

          初始化順序如下:

          1.導(dǎo)入的包首先被初始化,因此 simpleinterest 包首先被初始化并且它的 init 方法被調(diào)用。2.接下來初始化包級變量 p、r 和 t。3.接著調(diào)用 main.go 里的 init() 函數(shù)。4.最后調(diào)用 main() 函數(shù)。

          執(zhí)行程序?qū)敵觯?/p>

          Simple interest package initialized
          Main package initialized
          Simple interest calculation
          Simple interest is 500

          正如我們預(yù)期的那樣,simpleinterest 包的 init 函數(shù)首先被調(diào)用,然后是包級變量 p、r 和 t 的初始化,接下來調(diào)用 main 包的 init() 函數(shù),它檢查 p、r 和 t 是否小于零,如果 if 語句為真則會終止程序。關(guān)于 if 語句的使用我們將在另外章節(jié)介紹。在我們的程序里,所有的 if 條件都為 false,程序繼續(xù)執(zhí)行,最后調(diào)用 main() 函數(shù)。

          我們來簡單修改下代碼,

          將 main.go 文件的這行代碼:

          var p, r, t = 5000.010.01.0

          修改成:

          var p, r, t = -5000.010.01.0

          我們已將 p 初始化為負數(shù)。

          現(xiàn)在如果執(zhí)行程序就會輸出:

          Simple interest package initialized
          Main package initialized
          2020/02/15 21:25:12 Principal is less than zero

          因為 p 是負數(shù),所有程序在輸出 Principal is less than zero 之后便終止了。

          空白符 _

          源代碼里導(dǎo)入包如果不適用是非法的,編譯器編譯時會提示,這樣做的原因是為了避免未使用的包太多,這將顯著增加編譯時間。將 main.go 中的代碼替換為以下內(nèi)容:

          package main

          import (
                  "learnpackage/simpleinterest"
          )

          func main() {

          }

          執(zhí)行上面的代碼將會報錯:

          # learnpackage
          ./main.go:4:2: imported and not used: "learnpackage/simpleinterest"

          但是在平時開發(fā)時,導(dǎo)入一個包可能現(xiàn)在不用,在之后代碼的某個地方使用是很常見的,這時候該怎么辦?

          這時候空白符 _ 就能派上用場了,上面代碼的報錯可以使用空白符消除。

          package main

          import (
                  "learnpackage/simpleinterest"
          )

          var _ = simpleinterest.Calculate

          func main() {

          }

          上面的代碼行 var _ = simpleinterest.Calculate 雖然能消除錯誤,但是不建議這種方式,我們應(yīng)該特別留意這類代碼,并在程序開發(fā)完成之后刪除,包括導(dǎo)入但未使用的包。因此,建議在使用 import 導(dǎo)入包時使用 _ 消除此類錯誤。

          有時我們導(dǎo)入一個包只是為了確保初始化,即使我們不需要使用包中的任何函數(shù)或變量。例如,我們可能需要確保調(diào)用 simpleinterest 包的 init 函數(shù),即使我們不需要用到包里的任何函數(shù)或者變量。這種情況下也可以使用 _ 空白標識符,如下所示:

          package main

          import (
              _ "learnpackage/simpleinterest"
          )

          func main() {

          }

          執(zhí)行上面的代碼會輸出 Simple Interest package initialized,我們已經(jīng)成功地初始化了 simpleinterest 包,即使它沒有在代碼中的任何地方被使用。

          via: https://golangbot.com/go-packages/
          作者:Naveen R

          ------------------- End -------------------

          往期精彩文章推薦:

          歡迎大家點贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持

          想加入Go學(xué)習(xí)群請在后臺回復(fù)【入群

          萬水千山總是情,點個【在看】行不行

          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  豆花视频无码在线 | 中日韩欧美在线视频 | 99福利导航 | 人人操人人摸人人操 | 日韩在线黄 |