Les choses que vous pouvez faire avec make
cela que vous ne pouvez pas faire autrement:
- Créer une chaîne
- Créer une carte avec un espace préalloué
- Créer une tranche avec espace pré-alloué ou avec len! = Cap
C'est un peu plus difficile à justifier new
. La principale chose que cela facilite est la création de pointeurs vers des types non composites. Les deux fonctions ci-dessous sont équivalentes. On est juste un peu plus concis:
func newInt1() *int { return new(int) }
func newInt2() *int {
var i int
return &i
}
m := map[string]int{}
lieu dem := make(map[string]int)
? pas besoin de préallouer la taille également.Go propose plusieurs méthodes d'allocation de mémoire et d'initialisation de valeur:
&T{...}
,&someLocalVar
,new
,make
L'allocation peut également se produire lors de la création de littéraux composites.
new
peut être utilisé pour allouer des valeurs telles que des entiers,&int
est illégal:La différence entre
new
etmake
peut être vue en regardant l'exemple suivant:Supposons que Go n'a pas
new
etmake
, mais il a la fonction intégréeNEW
. Ensuite, l'exemple de code ressemblerait à ceci:Le
*
serait obligatoire , donc:Oui, la fusion
new
etmake
en une seule fonction intégrée est possible. Cependant, il est probable qu'une seule fonction intégrée entraînerait plus de confusion chez les nouveaux programmeurs Go que d'avoir deux fonctions intégrées.Compte tenu de tous les points ci-dessus, il semble plus approprié
new
etmake
séparé.la source
int
est créé.make(Point)
etmake(int)
dans ces 2 dernières lignes?make
La fonction alloue et initialise uniquement un objet de type tranche, carte ou chan. Commenew
, le premier argument est un type. Mais, cela peut aussi prendre un deuxième argument, la taille. Contrairement à new, le type de retour de make est le même que le type de son argument, pas un pointeur sur celui-ci. Et la valeur allouée est initialisée (non mise à zéro comme dans new). La raison en est que tranche, carte et chan sont des structures de données. Ils doivent être initialisés, sinon ils ne seront pas utilisables. C'est la raison pour laquelle new () et make () doivent être différents.Les exemples suivants de Efficace Go le montrent très clairement:
la source
new([]int)
, il alloue simplement de la mémoire à [] int, mais ne s'initialise pas, il revient donc simplementnil
; pas le pointeur vers la mémoire car il est inutilisable.make([]int)
alloue et initialise pour qu'il soit utilisable, puis retourne son adresse.new(T)
- Alloue de la mémoire et la met à zéro pour le type T .. ..c'est-à-dire
0
pour int ,""
pour chaîne etnil
pour les types référencés ( tranche , carte , chan )Notez que les types référencés ne sont que des pointeurs vers certaines structures de données sous-jacentes , qui ne seront pas créées par l'
new(T)
exemple: en cas de tranche , le tableau sous-jacent ne sera pas créé, donc ne
new([]int)
renvoie un pointeur vers rienmake(T)
- Alloue de la mémoire pour les types de données référencés ( tranche , carte , chan ), plus initialise leurs structures de données sous-jacentesExemple: en cas de tranche , le tableau sous-jacent sera créé avec la longueur et la capacité spécifiées
Gardez à l'esprit que, contrairement à C, un tableau est un type primitif dans Go!
Cela étant dit:
make(T)
se comporte comme une syntaxe littérale compositenew(T)
se comporte commevar
(lorsque la variable n'est pas initialisée)Exécutez le programme
Pour en savoir plus:
https://golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make
la source
Vous devez
make()
créer des canaux et des cartes (et des tranches, mais ceux-ci peuvent également être créés à partir de tableaux). Il n'y a pas d'autre moyen de les créer, vous ne pouvez donc pas les supprimermake()
de votre lexique.Quant à
new()
, je ne connais aucune raison pour laquelle vous en avez besoin lorsque vous pouvez utiliser la syntaxe struct. Il a cependant une signification sémantique unique, qui est "créer et renvoyer une structure avec tous les champs initialisés à leur valeur zéro", ce qui peut être utile.la source
En dehors de tout ce qui est expliqué dans Effective Go , la principale différence entre
new(T)
et&T{}
est que ce dernier effectue explicitement une allocation de tas. Cependant, il convient de noter que cela dépend de la mise en œuvre et peut donc être sujet à changement.La comparaison
make
avecnew
n'a pas de sens car les deux remplissent des fonctions entièrement différentes. Mais cela est expliqué en détail dans l'article lié.la source
&T{}
effectue explicitement une allocation de tas est AFAIK qui n'est basée sur rien dans les spécifications. En fait, je crois que les analyses d'échappement conservent déjà ce * T sur la pile autant que possible de la même manière qu'avecnew(T)
.new (T): il renvoie un pointeur pour taper T une valeur de type * T, il alloue et met à zéro la mémoire. new (T) est équivalent à & T {} .
make (T): il retourne une valeur initialisée de type T , il alloue et initialise la mémoire. Son utilisé pour les tranches, la carte et les canaux.
la source