Ответ
Функция make()
— это встроенная функция в Go, предназначенная исключительно для инициализации трёх встроенных ссылочных типов: срезов (slices), карт (maps) и каналов (channels).
Основная задача make()
— выделить память для базовой структуры данных, на которую ссылается тип, и вернуть инициализированный (не нулевой) экземпляр этого типа.
Синтаксис:
- Срезы:
make([]T, length, capacity)
— создаёт срез с указанной длиной и ёмкостью. - Карты:
make(map[K]V, initialCapacity)
— создаёт карту с предварительно выделенной памятью дляinitialCapacity
элементов, что помогает избежать лишних аллокаций при росте карты. - Каналы:
make(chan T, bufferSize)
— создаёт канал. ЕслиbufferSize
> 0, канал будет буферизированным.
Пример:
// Создаем срез int длиной 5 и ёмкостью 10
s := make([]int, 5, 10)
fmt.Println(len(s), cap(s)) // Вывод: 5 10
// Создаем карту для хранения пар string:int
m := make(map[string]int)
m["age"] = 30
// Создаем буферизированный канал на 3 элемента
ch := make(chan int, 3)
Ключевое отличие make()
от new()
Это частый вопрос на собеседованиях, и разница принципиальна:
Характеристика | make(T) | new(T) |
---|---|---|
Назначение | Инициализирует срезы, карты и каналы | Выделяет память для любого типа и обнуляет её |
Возвращаемое значение | Возвращает значение типа T (например, []int ) | Возвращает указатель на значение *T (например, *int ) |
Результат | Готовый к использованию, инициализированный объект | Указатель на нулевое значение типа T |
Простой пример для понимания:
// new возвращает указатель на нулевое значение int (т.е. на 0)
var p_int *int = new(int)
fmt.Println(*p_int) // 0
// make возвращает готовую к использованию карту
var m map[string]int = make(map[string]int)
m["test"] = 1 // Работает!
// А так было бы с new - паника!
// var m_new *map[string]int = new(map[string]int)
// (*m_new)["test"] = 1 // panic: assignment to entry in nil map
Использование new(map[string]int)
создаст указатель на nil
-карту, в которую нельзя записывать данные без дополнительной инициализации через make()
.