La función make en Go se utiliza exclusivamente para inicializar objetos de los tipos: slice, map y channel. Asigna la estructura de datos necesaria y devuelve un objeto listo para usar (¡no un puntero!).
Ejemplos:
s := make([]int, 5, 10) // slice de longitud 5, capacidad 10 m := make(map[string]int) // mapa vacío ch := make(chan int, 2) // canal con búfer de 2
Detalles:
slice, los parámetros son: longitud (len) y (opcionalmente) capacidad (cap).map y chan — solo capacidad (tamaño/búfer inicial) (opcional).make devuelve un objeto ya inicializado, listo para usar.make no se utiliza; se inicializan mediante literales o new (que devuelve un puntero al valor cero).Comparación con new:
new(T) devuelve *T, donde todos los campos son nulos.make(T) devuelve T solo para tres tipos: slice, map, chan.¿Se puede obtener un mapa funcional a través de new en lugar de make?
m := new(map[string]int) (*m)["a"] = 1 // ¿Qué sucederá?
Muchos piensan que esto es correcto, pero ocurrirá un panic en tiempo de ejecución: assignment to entry in nil map. ¡Porque la variable *m es nil!
Correcto: usar make:
m := make(map[string]int) m["a"] = 1 // OK
Historia
En un microservicio para almacenar caché, se creó un mapa a través de var cache map[string]interface{} sin inicialización con make, lo que provocó un panic en producción al escribir con rastros de pila confusos. El problema se encontró solo después de analizar el código: el mapa era nil.
Historia
Al escribir un pipeline de datos, olvidaron el búfer del canal y crearon a través de make(chan int). Como resultado, las goroutines se bloqueaban esperando lectura, aunque se esperaba una comunicación asincrónica. El error se notó solo durante una prueba a gran escala.
Historia
En un proyecto, donde la inicialización se hacía a través de new, algunos desarrolladores intentaron usar new([]int) en lugar de make([]int, 10), obteniendo un puntero al nil slice y pánico en tiempo de ejecución al intentar escribir por primera vez.