簡體   English   中英

golang package 導入流程是如何工作的,有沒有辦法在同一個模塊中多次初始化一個 package?

[英]How does the golang package import flow work and is there a way to initialize one package multiple times within the same module?

我是 golang 的新手,目前正在研究包和導入它們的工作原理。 我對這次進口有幾個問題。 我正在閱讀這篇文章(它有超過 7k 個贊,所以我猜它是准確的 + 這是當我輸入golang packages時谷歌首先給我的)。

為了解釋我不明白的地方,我會先寫下項目結構是什么樣子的,以及所有文件的內容是什么。

pkg
├── mypkg
|  └── mypkg.go
|
├── pkg1
|  └── pkg1.go
|
└── pkg2
   └── pkg2.go
go.mod
main.go

如您所見,我有包含 3 個包的模塊(4 個包括主包)。 所有包裹的內容如下所列。

pkg1.go 的內容

package pkg1

import (
    "fmt"
    "mymod/pkg/mypkg"
)

func init() {
    fmt.Println("Hello everyone from pkg1 init")
}

func HelloFromPkg1() {
    fmt.Println("Hello from pk1")
    mypkg.Print()
}

pkg2.go 的內容

package pkg2

import (
    "fmt"
    "mymod/pkg/mypkg"
)

func init() {
    fmt.Println("Hello everyone from pkg2 init")
}

func HelloFromPkg2() {
    fmt.Println("Hello from pk2")
    mypkg.Print()
}

mypkg 的內容

package mypkg

import "fmt"

func init() {
    fmt.Println("Hello everyone from mypkg init")
}

var prom = 10

func Print() {
    fmt.Printf("address of prom inside mypkg is: %p\n", &prom)
}

main.go 的內容

package main

import (
    "fmt"
    "mymod/pkg/pkg1"
    "mymod/pkg/pkg2"
)

func init() {
    fmt.Println("Hello everyone from main init")
}

func main() {
    pkg1.HelloFromPkg1()
    pkg2.HelloFromPkg2()
}

因此, main.go包括pkg1pkg2並且pkgpkg2都包括mypkg 我參考的文章陳述如下(粗體):

要記住的主要事情是,導入的 package 每個 package 只初始化一次。

考慮到這一點,我期待這樣的事情成為我程序的 output:

Hello everyone from mypkg init
Hello everyone from pkg1 init
Hello everyone from mypkg init
Hello everyone from pkg2 init
Hello everyone from main init
Hello from pk1
address of prom inside mypkg is: 0xfee360 (some address)
Hello from pk2
address of prom inside mypkg is: 0xf321a3 (another address)

我的期望是將遵循以下步驟:

  • 進主package(1)
  • pkg1 package 已初始化 (2)
    • mypkg package 已初始化(2.1)
      • mypkg 中的所有全局變量都已初始化 - 在我的例子中為prom (2.1.1)
      • 調用 mypkg 的 init function (2.1.2)
    • pkg1 的 init function 被稱為 (2.2)
  • pkg2 package 已初始化 (3)
    • mypkg package 已初始化 (3.1)
      • mypkg 中的所有全局變量都已初始化 - 在我的例子中為prom (3.1.1)
      • 調用 mypkg 的 init function (3.1.2)
    • pkg2 的 init function 被稱為 (3.2)
  • main package 初始化(4)
  • 調用 main 的 init function (5)
  • main package 的 main function 被稱為 (6)

而不是它,我得到以下 output:

Hello everyone from mypkg init
Hello everyone from pkg1 init
Hello everyone from pkg2 init
Hello everyone from main init
Hello from pk1
address of prom inside mypkg is: 0x8fe360
Hello from pk2
address of prom inside mypkg is: 0x8fe360

看起來 mypkg在第一次導入期間只初始化了一次?此外,全局變量prom的地址在 pkg1 和 pkg2 中是相同的(在本例中為0x8fe360 )。

所以我的問題是:

  1. 這篇文章的作者是否犯了錯誤? 導入的包不是每個 package 只初始化一次,而是每個模塊一次
  2. 這是否意味着來自一個 package 的全局變量在整個模塊(相同地址)中始終相同,無論包含 package 多少次以及來自何處? 我的意思是它們只會在第一次導入時初始化一次
  3. 有什么方法可以讓我的“流程”發揮作用嗎? 我的意思是每次導入都有一個 package 的獨立初始化? 在我的示例中,這意味着mypkgpkg1中初始化一次,在pkg2中初始化另一次。
  4. go 有沒有人有一篇關於包和模塊的好文章,如果我看的不正確?

我知道對於某些人來說,這些問題是關於 golang 的一些基礎知識,但對於我這個初學者來說,這造成了一些誤解。 更重要的是,該程序的工作結果與谷歌搜索中最先出現的文章的作者所寫的不符。 歡迎任何幫助。 一切順利!

程序中包含的包是一個集合,它是從main開始的所有導入包的傳遞閉包。 那是:

  • 它是一套。 每個導入的 package 只包含一次。 這意味着,如果您在 package 中定義了一個變量,則該變量只會出現一次。
  • 所有導入的包,以及它們遞歸導入的包,都包含在最終的二進制文件中。

至於初始化:你的步驟是正確的,只是mypkg只初始化了一次。 二進制文件中沒有mypkg的多個副本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM