Home  >  Article  >  Backend Development  >  How does the golang package import process work? Is there a way to initialize a package multiple times in the same module?

How does the golang package import process work? Is there a way to initialize a package multiple times in the same module?

PHPz
PHPzforward
2024-02-06 08:54:08941browse

golang 包导入流程如何工作?是否有一种方法可以在同一模块中多次初始化一个包?

Question content

I am new to golang and currently looking into packages and how importing them works. I have a few questions about this import. I'm reading this post (it has over 7k likes so I guess it's accurate and it's the first thing google gives me when I type golang package ).

In order to explain what I don't understand, let me first write about what the project structure is like and what the contents of all the files are.

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

As you can see, I have a module with 3 packages (4 packages including the main package). The contents of all packages are listed below.

pkg1.go Content:

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 Content:

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

Contents of 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 Content:

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

Thus, main.go contains pkg1 and pkg2, and pkg1 and pkg2 both containmypkg. The article I cited states the following (in bold):

the main thing to remember is, an imported package is initialized only once per package.

With this in mind, I would expect the output of my program to be something like this:

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)

My expectation is to follow these steps:

  • Enter the main package (1)
  • pkg1 package has been initialized (2)
    • mypkg package initialized (2.1)
      • All global variables in mypkg are initialized -prom In my case (2.1.1)
      • Call the init function of mypkg (2.1.2)
    • Call the init function of pkg1 (2.2)
  • pkg2 package has been initialized (3)
    • mypkg package initialized (3.1)
      • All global variables in mypkg are initialized -prom In my case (3.1.1)
      • Call the init function of mypkg (3.1.2)
    • Call the init function of pkg2 (3.2)
  • Main package initialization (4)
  • Call main's init function (5)
  • The main function of the main package is called (6)

Instead, I get the following 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

It looks like mypkg is only initialized once during the first import? ! Additionally, the global variable prom has the same address in pkg1 and pkg2 (0x8fe360 in this case).

So my question is:

  1. Did the author of the article make a mistake? The imported packages are not initialized only once per package, but once per module?
  2. Does this mean that global variables in a package are always the same (same address) throughout the module, no matter how many times the package is included and from where? I mean they are only initialized once during the first import?
  3. Is there any way to make my "flow" work? I mean each import will initialize a package independently? In my example this means mypkg is initialized once in pkg1 and another time in pkg2.
  4. If what I read is incorrect, does anyone have a good article about packages and modules in go?

I know that for some people these questions are about some basic knowledge of golang, but for me as a beginner it caused some misunderstandings. What's more, the results of the program's work didn't match what the authors of the articles that came up first in Google searches had written. Any help is welcome. wish all the best!


Correct answer


The packages contained in the program are a set, which is the transitive closure of all imported packages starting from main. Right now:

  • This is a set. Each imported package is included only once. This means that if you define a variable in a package, it appears only once.
  • All imported packages and the packages they import recursively are included in the final binary.

As for initialization: your steps are correct, just mypkg only initialize once. There are not multiple copies of mypkg in the binary.

The above is the detailed content of How does the golang package import process work? Is there a way to initialize a package multiple times in the same module?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete