Los documentos de introducción dedican muchos párrafos a explicar la diferencia entre new()
y make()
, pero en la práctica, puede crear objetos dentro del ámbito local y devolverlos.
¿Por qué usarías el par de asignadores?
Cosas que puedes hacer con las make
que no puedes hacer de otra manera:
Es un poco más difícil de justificar new
. Lo principal que facilita es crear punteros a tipos no compuestos. Las dos funciones siguientes son equivalentes. Uno es un poco más conciso:
func newInt1() *int { return new(int) }
func newInt2() *int {
var i int
return &i
}
m := map[string]int{}
lugar dem := make(map[string]int)
? No es necesario preasignar el tamaño también.Go tiene múltiples formas de asignación de memoria e inicialización de valor:
&T{...}
,&someLocalVar
,new
,make
La asignación también puede ocurrir al crear literales compuestos.
new
puede usarse para asignar valores como enteros,&int
es ilegal:La diferencia entre
new
ymake
se puede ver mirando el siguiente ejemplo:Supongamos que Go no tiene
new
ymake
, pero tiene la función incorporadaNEW
. Entonces el código de ejemplo se vería así:El
*
sería obligatorio , entonces:Sí, es posible fusionar
new
ymake
formar una sola función integrada. Sin embargo, es probable que una sola función integrada genere más confusión entre los nuevos programadores de Go que tener dos funciones integradas.Teniendo en cuenta todos los puntos anteriores, parece más apropiado
new
ymake
permanecer separado.fuente
int
se crea.make(Point)
ymake(int)
en esas 2 últimas líneas?make
La función asigna e inicializa un objeto de tipo sector, mapa o chan únicamente. Comonew
, el primer argumento es un tipo. Pero, también puede tomar un segundo argumento, el tamaño. A diferencia del nuevo, el tipo de retorno de make es el mismo que el tipo de su argumento, no un puntero al mismo. Y el valor asignado se inicializa (no se establece en valor cero como en new). La razón es que el corte, el mapa y el chan son estructuras de datos. Deben inicializarse, de lo contrario no serán utilizables. Esta es la razón por la que new () y make () deben ser diferentes.Los siguientes ejemplos de Effective Go lo dejan muy claro:
fuente
new([]int)
, solo asigna memoria para [] int, pero no se inicializa, por lo que solo regresanil
; no es el puntero a la memoria porque es inutilizable.make([]int)
asigna e inicializa para que sea utilizable, luego devuelva su dirección.new(T)
- Asigna memoria y la establece en el valor cero para el tipo T ....esto es
0
para int ,""
para string ynil
para los tipos referenciados ( slice , map , chan )Tenga en cuenta que los tipos referenciados son solo punteros a algunas estructuras de datos subyacentes , que no se crearán con el
new(T)
Ejemplo: en caso de división , la matriz subyacente no se creará, por lo tanto, no
new([]int)
devuelve un puntero a nadamake(T)
- Asigna memoria para los tipos de datos referenciados ( corte , mapa , chan ), además de inicializar sus estructuras de datos subyacentesEjemplo: en caso de corte , la matriz subyacente se creará con la longitud y capacidad especificadas.
Tenga en cuenta que, a diferencia de C, una matriz es un tipo primitivo en Go!
Habiendo dicho eso:
make(T)
se comporta como sintaxis literal compuestanew(T)
se comporta comovar
(cuando la variable no se inicializa)Ejecuta el programa
Más información:
https://golang.org/doc/effective_go.html#allocation_new https://golang.org/doc/effective_go.html#allocation_make
fuente
Necesita
make()
crear canales y mapas (y segmentos, pero también se pueden crear a partir de matrices). No hay una forma alternativa de hacerlos, por lo que no puede eliminarlosmake()
de su léxico.En cuanto a
new()
, no sé de ninguna razón por qué lo necesitas cuando puedes usar la sintaxis de estructura. Sin embargo, tiene un significado semántico único, que es "crear y devolver una estructura con todos los campos inicializados a su valor cero", lo que puede ser útil.fuente
Además de todo lo explicado en Effective Go , la principal diferencia entre
new(T)
y&T{}
es que este último realiza explícitamente una asignación de montón. Sin embargo, debe tenerse en cuenta que esto depende de la implementación y, por lo tanto, puede estar sujeto a cambios.Comparando
make
anew
tiene mucho sentido ya que los dos realizan funciones completamente diferentes. Pero esto se explica en detalle en el artículo vinculado.fuente
&T{}
realiza explícitamente una asignación de montón es AFAIK no basada en nada en las especificaciones. En realidad, creo que el análisis de escape ya mantiene tal * T en la pila siempre que sea posible de la misma manera que connew(T)
.nuevo (T): devuelve un puntero para escribir T un valor de tipo * T, asigna y pone a cero la memoria. nuevo (T) es equivalente a & T {} .
make (T): devuelve un valor inicializado de tipo T , asigna e inicializa la memoria. Se utiliza para sectores, mapas y canales.
fuente