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

PHPz
Release: 2024-02-06 08:54:08
forward
940 people have browsed it

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
Copy after login

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()
}
Copy after login

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()
}
Copy after login

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)
}
Copy after login

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()
}
Copy after login

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.
Copy after login

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)
Copy after login

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
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!