Maison > développement back-end > Golang > Comment fonctionne le processus d'importation de packages Golang ? Existe-t-il un moyen d'initialiser un package plusieurs fois dans le même module ?

Comment fonctionne le processus d'importation de packages Golang ? Existe-t-il un moyen d'initialiser un package plusieurs fois dans le même module ?

PHPz
Libérer: 2024-02-06 08:54:08
avant
990 Les gens l'ont consulté

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

Contenu de la question

Je suis nouveau sur Golang et j'étudie actuellement les packages et leur fonctionnement. J'ai quelques questions sur cette importation. Je lis ce post (il a plus de 7 000 likes donc je suppose que c'est exact + c'est la première chose que Google me donne quand je tape golang 包 ).

Afin d'expliquer ce que je ne comprends pas, permettez-moi d'abord d'écrire sur la structure du projet et le contenu de tous les fichiers.

pkg
├── mypkg
|  └── mypkg.go
|
├── pkg1
|  └── pkg1.go
|
└── pkg2
   └── pkg2.go
go.mod
main.go
Copier après la connexion

Comme vous pouvez le constater, j'ai des modules avec 3 packages (4 packages dont le package principal). Le contenu de tous les packages est répertorié ci-dessous.

Contenu du

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()
}
Copier après la connexion
Contenu de

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()
}
Copier après la connexion
Contenu de

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)
}
Copier après la connexion

contenu 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()
}
Copier après la connexion

Par conséquent, main.go 包含 pkg1pkg2,并且 pkg1pkg2 都包含 mypkg. L'article que j'ai cité indique ce qui suit (en gras) :

the main thing to remember is, an imported package is initialized only once per package.
Copier après la connexion

En gardant cela à l'esprit, je m'attendrais à ce que le résultat de mon programme ressemble à ceci :

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)
Copier après la connexion

Mon attente est de suivre ces étapes :

  • Entrez le package principal (1)
  • paquet pkg1 initialisé (2)
      Le package
    • mypkg a été initialisé (2.1)
      • Toutes les variables globales de mypkg sont initialisées -prom Dans mon cas (2.1.1)
      • Appelez la fonction init de mypkg (2.1.2)
    • Appelez la fonction init du pkg1 (2.2)
  • paquet pkg2 initialisé (3)
      Le package
    • mypkg a été initialisé (3.1)
      • Toutes les variables globales de mypkg sont initialisées -prom Dans mon cas (3.1.1)
      • Appelez la fonction init de mypkg (3.1.2)
    • Appelez la fonction init de pkg2 (3.2)
  • Initialisation du package principal (4)
  • Appelez la fonction d'initialisation principale (5)
  • La fonction principale du package principal s'appelle (6)

Au lieu de cela, j'obtiens le résultat suivant :

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
Copier après la connexion

On dirait que mypkg n'est initialisé qu'une seule fois lors de la première importation ? ! De plus, la variable globale prom 在 pkg1 和 pkg2 中的地址是相同的(在本例中为 0x8fe360 a la même adresse dans pkg1 et pkg2 (0x8fe360 dans ce cas).

Ma question est donc :

  1. L'auteur de l'article a-t-il commis une erreur ? Les packages importés ne sont pas initialisés une seule fois par package, mais une fois par module ? Cela signifie-t-il que les variables globales d'un package sont toujours les mêmes (même adresse) dans tout le module, peu importe le nombre de fois où le package est inclus et d'où ? Je veux dire qu'ils ne sont initialisés
  2. qu'une seule fois
  3. lors de la première importation ? Y a-t-il un moyen de faire fonctionner mon « flow » ? Je veux dire que chaque importation initialisera un package indépendamment ? Dans mon exemple, cela signifie initialiser une fois de plus dans
  4. .
  5. mypkgpkg1 中初始化一次,在 pkg2Si ce que je lis est incorrect, quelqu'un a-t-il un bon article sur les packages et modules en cours ?
  6. Je sais que pour certaines personnes, ces questions concernent des connaissances de base du golang, mais pour moi, en tant que débutant, cela a provoqué quelques malentendus. De plus, les résultats du programme ne correspondaient pas à ceux écrits par les auteurs des articles apparus en premier dans les recherches Google. Toute aide est la bienvenue. je souhaite tout le meilleur!

Bonne réponse

Les packages contenus dans le programme sont un ensemble qui est la fermeture transitive de tous les packages importés à partir de
. C'est à dire :

main

C'est un ensemble. Chaque package importé n'est inclus qu'une seule fois. Cela signifie que si vous définissez une variable dans un package, elle n'apparaît qu'une seule fois.
  • Tous les packages importés et les packages qu'ils importent de manière récursive sont inclus dans le binaire final.
  • Quant à l'initialisation : vos étapes sont correctes, juste plusieurs copies de
.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal