четверг, 24 января 2019 г.

Эффективный Go: данные, аллокация с помощью make

Встроенная функция make(T, args) служит цели, отличающейся от new(T). Она создает только срезы, карты и каналы и возвращает инициализированное (не обнуленное) значение типа T(не *T). Причиной различия является то, что эти три типа представляют под капотом ссылки на структуры данных, которые должны быть инициализированы перед использованием. Например, срез (slice) представляет собой дескриптор из трех элементов, содержащий указатель на данные (внутри массива), длину и емкость, и пока эти элементы не будут инициализированы, срез будет равен nil. Для срезов, карт и каналов, make инициализирует внутреннюю структуру данных и подготавливает значение для использования. Например:

make([]int, 10, 100)

аллоцирует массив из 100 int'ов, а затем создает структуру среза длиной 10 и вместимостью 100, указывающую на первые 10 элементов массива. (При создании среза емкость можно опустить) Напротив, new([] int) возвращает указатель на вновь выделенный обнуленную структуру среза, то есть указатель на значение фрагмента nil.

Следующие примеры иллюстрируют разницу между new и make.

// аллоцирует структуру среза; *p == nil; используется редко
var p *[]int = new([]int) 

// срез v теперь ссылается на новый массив из 100 int'ов      
var v  []int = make([]int, 100) 

// Излишне сложно:
var p *[]int = new([]int)
*p = make([]int, 100, 100)

// Идиоматично:
v := make([]int, 100)

Помните, что make применяется только к картам, срезам и каналам и не возвращает указатель. Чтобы получить явный указатель, аллоцируйте с помощью new или выберите адрес переменной явно.


Читайте также:


Комментариев нет:

Отправить комментарий