go

go - ¿Por qué debería hacer() o nuevo()?



(6)

Además de todo lo explicado en golang.org/doc/effective_go.html#allocation_new , 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.

Comparar make a new tiene poco sentido ya que ambos realizan funciones completamente diferentes. Pero esto se explica en detalle en el artículo vinculado.

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ía el (francamente tonto) par de asignadores?


Go tiene múltiples formas de asignación de memoria e inicialización de valores:

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

La asignación también puede ocurrir al crear literales compuestos.

new se puede usar para asignar valores como enteros, &int es ilegal:

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 diferencia entre new y make se puede ver mirando el siguiente ejemplo:

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

Supongamos que Go no tiene new y make , pero tiene la función incorporada NEW . Entonces el código de ejemplo se vería así:

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

El * sería obligatorio , entonces:

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í, es posible combinar new funciones y make en una única función incorporada. Sin embargo, es probable que una sola función integrada genere más confusión entre los nuevos programadores Go que tener dos funciones incorporadas.

Teniendo en cuenta todos los puntos anteriores, parece más apropiado para los new y make que permanezcan separados.


Las cosas que puedes hacer con make no lo puedes hacer de otra manera:

  • Crea un canal
  • Crear un mapa con espacio preasignado
  • Crea un sector con espacio preasignado o con len! = Cap

Es un poco más difícil de justificar new . Lo principal es que facilita la creación de punteros a tipos no compuestos. Las dos funciones a continuación son equivalentes. Uno es solo un poco más conciso:

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


Necesita make() para crear canales y mapas (y sectores, pero también se pueden crear a partir de matrices). No existe una forma alternativa de hacer eso, por lo que no puede eliminar make() de su léxico.

En cuanto a new() , no sé por ningún motivo por qué lo necesitas cuando puedes usar struct sintaxis. Sin embargo, tiene un significado semántico único, que es "crear y devolver una estructura con todos los campos inicializados a su valor cero", que puede ser útil.


make function asigna e inicializa un objeto de tipo slice, map o chan únicamente. Como nuevo, el primer argumento es un tipo. Pero, también puede tomar un segundo argumento, el tamaño. A diferencia de lo nuevo, el tipo de devolución 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 nuevo). La razón es que slice, map y chan son estructuras de datos. Deben inicializarse, de lo contrario no serán utilizables. Esta es la razón por la cual new () y make () deben ser diferentes.

Los siguientes ejemplos de Effective Go lo dejan muy claro:

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


new (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 usa para rebanadas, mapas y canales.