Perché dovrei fare () o nuovo ()?

I documenti introduttivi dedicano molti paragrafi alla spiegazione della differenza tra new() e make() , ma in pratica è ansible creare oggetti nell’ambito locale e restituirli.

Perché dovresti usare la coppia (francamente sciocca) di allocatori?

Le cose che puoi fare make che non puoi fare diversamente:

  • Crea un canale
  • Crea una mappa con spazio preallocato
  • Crea una fetta con spazio preallocato o con len! = Cap

È un po ‘più difficile giustificare il new . La cosa principale che semplifica è la creazione di puntatori a tipi non compositi. Le due funzioni di seguito sono equivalenti. Uno è solo un po ‘più conciso:

 func newInt1() *int { return new(int) } func newInt2() *int { var i int return &i } 

Go ha molteplici modi di allocazione della memoria e inizializzazione del valore:

&T{...} , &someLocalVar , new , make

L’allocazione può anche avvenire quando si creano letterali compositi.


new può essere usato per allocare valori come interi, &int è illegale:

 new(Point) &Point{} // OK &Point{2, 3} // Combines allocation and initialization new(int) &int // Illegal // Works, but it is less convenient to write than new(int) var i int &i 

La differenza tra new e make può essere vista guardando il seguente esempio:

 p := new(chan int) // p has type: *chan int c := make(chan int) // c has type: chan int 

Supponiamo che Go non abbia new e funzioni, ma ha la funzione integrata NEW . Quindi il codice di esempio sarebbe simile a questo:

 p := NEW(*chan int) // * is mandatory c := NEW(chan int) 

Il * sarebbe obbligatorio , quindi:

 new(int) --> NEW(*int) new(Point) --> NEW(*Point) new(chan int) --> NEW(*chan int) make([]int, 10) --> NEW([]int, 10) new(Point) // Illegal new(int) // Illegal 

Sì, è ansible unire new e make in un’unica funzione integrata. Tuttavia, è probabile che una singola funzione incorporata porterebbe a una maggiore confusione tra i nuovi programmatori di Go che avere due funzioni incorporate.

Considerando tutti i punti di cui sopra, sembra più appropriato per il new e make per rimanere separati.

make function alloca e inizializza un object di tipo slice, map o solo chan. Come nuovo, il primo argomento è un tipo. Ma può anche prendere un secondo argomento, la dimensione. Diversamente dal nuovo, il tipo restituito da make è uguale al tipo del suo argomento, non un puntatore ad esso. E il valore assegnato viene inizializzato (non impostato su zero come nel nuovo). La ragione è che slice, map e chan sono strutture dati. Devono essere inizializzati, altrimenti non saranno utilizzabili. Questo è il motivo per cui new () e make () devono essere diversi.

I seguenti esempi di Effective Go lo rendono molto chiaro:

 p *[]int = new([]int) // *p = nil, which makes p useless v []int = make([]int, 100) // creates v structure that has pointer to an array, length field, and capacity field. So, v is immediately usable 

A parte tutto ciò che viene spiegato in Effective Go , la differenza principale tra new(T) e &T{} è che quest’ultima esegue esplicitamente un’allocazione dell’heap. Tuttavia, va notato che questo dipende dall’implementazione e quindi potrebbe essere sobject a modifiche.

Comparare make to new ha poco senso dato che i due svolgono funzioni completamente diverse. Ma questo è spiegato in dettaglio nell’articolo collegato.

È necessario make() per creare canali e mappe (e sezioni, ma anche quelli possono essere creati dagli array). Non esiste un modo alternativo per crearli, quindi non puoi rimuovere make() dal tuo lessico.

Per quanto riguarda new() , non conosco alcuna ragione per cui ne hai bisogno quando puoi usare la syntax struct. Tuttavia ha un significato semantico unico, che è “creare e restituire una struttura con tutti i campi inizializzati al loro valore zero”, che può essere utile.

new (T): restituisce un puntatore per digitare T un valore di tipo * T, assegna e azzera la memoria. nuovo (T) è equivalente a & T {} .

make (T): restituisce un valore inizializzato di tipo T , Alloca e inizializza la memoria. È usato per fette, mappa e canali.