I'm new to golang and I'm currently researching how packages and importing them works. I have a few questions about this import. I am reading this article (it has more than 7k likes so I guess it's accurate + it's first what google gives me when I type golang packages
).
To explain what I don't understand, I will first write what the project structure looks like and what the contents of all files are.
pkg
├── mypkg
| └── mypkg.go
|
├── pkg1
| └── pkg1.go
|
└── pkg2
└── pkg2.go
go.mod
main.go
As you can see, I have module with 3 packages (4 including main). The contents of all packages are listed below.
Content of the 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()
}
Content of the 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()
}
Content of the 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)
}
Content of the 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()
}
So, main.go
includes pkg1
and pkg2
and both pkg1
and pkg2
include mypkg
. The article I refer to states the following (it's bolded):
The main thing to remember is, an imported package is initialized only once per package.
Having that in mind, I am expecting something like this to be the output of my program:
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 that the following steps will be followed:
prom
in my case (2.1.1)prom
in my case (3.1.1)Instead of it, 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 initialized only once during the first import?! Also, the address of the global variable prom
is the same in pkg1 and pkg2 (in this case it's 0x8fe360
).
So my questions are:
mypkg
is initialized once in pkg1
and another time in pkg2
.I know for some these questions are some basics about golang, but for me as a beginner this caused some misunderstandings. All the more so since the result of the program's work does not match what the author of the article that comes up first during a Google search wrote. Any help is welcome. All the best!
The packages included in a program is a set that is the transitive closure of all imported packages starting from main
. That is:
As for initialization: your steps are correct, except that mypkg
is initialized only once. There are not multiple copies of mypkg
in the binary.