Translate

viernes, 3 de noviembre de 2023

Asignación de memoria con make en Go


La función make(T, args) tiene un propósito diferente al de new(T). Crea únicamente slices, maps, y channels y devuelve un valor inicializado (no puesto a cero) de tipo T (no *T). El motivo de la distinción es que estos tres tipos representan, encubiertamente, referencias a estructuras de datos que deben inicializarse antes de su uso. Un slice, por ejemplo, es un descriptor de tres elementos que contiene un puntero a los datos (dentro de un arreglo o vector), la longitud y la capacidad, y hasta que esos elementos se inicialicen, el slice es nulo. Para slices, map y chanels, make inicializa la estructura de datos interna y prepara el valor para su uso. Por ejemplo,


make([]int, 10, 100)


asigna una arreglo de entero de 100 elementos y luego crea una estructura slice con una longitud de 10 y una capacidad de 100 que apunta a los primeros 10 elementos de la matriz. (Al crear un slice, se puede omitir la capacidad). Por el contrario, new([]int) devuelve un puntero a una estructura de slice puesta a cero recién asignada, es decir, un puntero a un slice nulo.

Estos ejemplos ilustran la diferencia entre nuevo y fabricado.


var p *[]int = new([]int)       // allocates slice structure; *p == nil; rarely useful

var v  []int = make([]int, 100) // the slice v now refers to a new array of 100 ints


// Unnecessarily complex:

var p *[]int = new([]int)

*p = make([]int, 100, 100)


// Idiomatic:

v := make([]int, 100)


Recuerde que make se aplica solo a maps, slices y channels y no devuelve un puntero. Para obtener un puntero explícito, asigne nuevo o tome la dirección de una variable explícitamente.