web-dev-qa-db-fra.com

Pourquoi Golang n'autorise-t-il pas les cartes const?

Je voudrais créer une carte constante comme celle-ci:

const (
    running = map[string]string{
        "one": "ONE",
        "two": "TWO",
    }
)

cependant, chaque fois que je le fais, j'obtiens l'erreur suivante:

const initializer map[string]string literal is not a constant

Pourquoi est-ce le cas, pourquoi Golang ne les traite-t-il pas comme n'importe quelle autre variable?

23
anonrose

De https://golang.org/ref/spec#Constants :

Une valeur constante est représentée par une rune, un entier, une virgule flottante, un imaginaire ou un littéral de chaîne, un identifiant désignant une constante, une expression constante, une conversion avec un résultat constant ou la valeur de résultat de certains éléments intégrés. fonctions telles que unsafe.Sizeof appliquées à n'importe quelle valeur, cap ou len appliquées à certaines expressions, real et imag appliquées à une constante complexe et complexes appliquées aux constantes numériques.

tl; dr seuls les types numériques, les chaînes et les booléens peuvent être des constantes, des tableaux, des tranches et des cartes ne sont pas de type numérique.

19
OneOfOne

Mon point de vue est que cette décision était purement pragmatique: Go est un langage très terre-à-terre (par opposition à d'autres - plus "puristes"), et une propriété intéressante de certaines implémentations de cartes du monde réel est que y accéder en lecture pourrait mettre à jour leur représentation interne (!). Dites, ils pourraient rassembler et stocker des statistiques sur leur utilisation, ou ils pourraient rééquilibrer un arbre sous-jacent qui contient les compartiments de valeur, etc. - nécessitant très probablement deux implémentations de carte.

Vous pouvez également essayer de la regarder sous un autre angle: considérez une constante de chaîne. Une telle chose pourrait être facilement intégrée dans la section .rodata Du binaire résultant et être réellement représentée par l'adresse de ces données en mémoire (enfin, les chaînes dans Go sont plus compliquées mais ignorons ce détail). C'est-à-dire qu'une chaîne constante peut être vraiment "statique": c'est juste une série d'octets R/O statiques en mémoire - aussi simple que cela. Inversement, une carte est une bête très compliquée alimentée par une machinerie complexe, et chaque carte est un objet complexe spécial instancié au moment de l'exécution. C'est pourquoi vous ne pouvez même pas déclarez simplement une carte et utilisez-la: vous devez make() la première - tout comme les canaux, et pour la même raison.

Encore une fois, un hack pourrait éventuellement être fait pour prendre en charge des cartes constantes. Supposons qu'une implémentation puisse trier les clés de votre carte à l'avance, les sérialiser (avec des valeurs) dans une région contiguë de données R/O, puis utiliser la recherche binaire lors de l'exécution pour rechercher les valeurs. Ce serait terriblement inefficace pour les grandes cartes/certains motifs clés, mais cela fonctionnerait soi-disant. Pourtant, ce serait une implémentation de carte spécialisée complètement différente de celle "normale". Je pense que les développeurs de Go ont décidé que le compromis ne valait aucun avantage possible.

Deux notes de suivi:

  • Comme vous pouvez le voir, vous pouvez émuler relativement facilement une carte en lecture seule: avoir un littéral de tranche de certains types de struct incorporant à la fois les clés et les valeurs, triées à l'avance sur les clés, et encapsuler dans une fonction qui effectue une recherche binaire sur la clé.

  • Je préfère considérer les constantes de Go un peu comme des macros dans un langage de type C: elles sont non typées et se sentent comme étant textuelles (elles ne le sont pas mais je '' je parle de ressentir après tout) ;-)

    Assurez-vous de lire this pour un excellent aperçu.

3
kostix