В чем разница между новыми и make?

New не инициализирует память, она только нулирует ее. Он возвращает указатель на новое выделенное нулевое значение.

Make создает только срезы, карты и каналы и возвращает их инициализированным.

Что означает "инициализированный" в этом контексте? Какие еще существуют различия между новыми и make?

Ответ 1

Как уже упоминалось в разделе Создание срезов, карт и каналов:

Встроенная функция make принимает тип T, который должен быть типом среза, карты или канала, за которым может следовать список выражений, зависящий от типа.
Возвращает значение типа T (не *T).
Память инициализируется, как описано в разделе о начальных значениях.

Например, для типа слайс

make([]T, length, capacity)

создает тот же фрагмент, что и выделение массива и его разделение, поэтому эти два выражения эквивалентны:

make([]int, 50, 100)
new([100]int)[0:50]

Итак, здесь make создает срез и инициализирует его содержимое в зависимости от нулевого значения, если используется тип (здесь int, поэтому ' 0 ')

Вы можете узнать больше о необходимости сохранять новое и отделить в Go: зачем мне делать() или новый()?


Дэйв Чени только что написал хорошую статью: "В Go есть и make, и новые функции, что дает? "

Хотя make создает общие значения slice, map и channel, они все еще являются обычными значениями; make не возвращает значения указателя.

Если new был удален в пользу make, как бы вы создали указатель на инициализированное значение?

Использование new для создания указателя на нулевое значение slice, map или channel работает сегодня и согласуется с поведением new.

Для беспорядка, который они могут вызвать, make и new являются последовательными;

  • make делает только фрагменты, карты и каналы,
  • new только возвращает указатели на инициализированную память.

Ответ 2

Первое отличие - это тип: make(T, ...) всегда возвращает тип T, тогда как new(T, ...) всегда возвращает тип *T. Это говорит о том, что они очень разные.

new работает для всех типов и динамически выделяет пространство для переменной этого типа, инициализированной нулевым значением этого типа, и возвращает указатель на него.

Один из способов подумать, что

result = new(T)

всегда эквивалентно

var temp T
result = &temp

(другими словами, вы можете сделать то же самое, что new, задавая переменную данного типа, не инициализируя ее, а затем беря указатель на нее.)

make работает как своего рода "конструктор" для определенных встроенных типов (срез, карта или канал).

Ответ 3

enter image description here Встроенная функция new (T) выделяет "обнуленное" хранилище для нового элемента типа T и возвращает его адрес, значение типа * T. В терминологии Go он возвращает указатель на вновь назначенное нулевое значение типа T. Например, здесь есть три различных способа создания указателя p, который указывает на обнуляемое значение bytes.Buffer, каждый из которых эквивалентен:

// Allocate enough memory to store a bytes.Buffer value
// and return a pointer to the value address.
var buf bytes.Buffer
p := &buf

// Use a composite literal to perform allocation and
// return a pointer to the value address.
p := &bytes.Buffer{}

// Use the new function to perform allocation, which will
// return a pointer to the value address.
p := new(bytes.Buffer)

Функция make(), с другой стороны, представляет собой специальную встроенную функцию, которая используется для инициализации срезов, карт и каналов. Обратите внимание, что make() может использоваться только для инициализации срезов, карт и каналов, и что, в отличие от функции new(), make() не возвращает указатель.

Срезы, карты и каналы также можно инициализировать с помощью составных литеральных выражений, а также с помощью make(). Два различных (но эквивалентных) способа инициализации карты m, которая отображает строковые ключи на значения bool, приведены ниже в качестве примеров:

// Using make() to initialize a map.
m := make(map[string]bool, 0)

// Using a composite literal to initialize a map.
m := map[string]bool{}

// You can also initialize maps with initial data using a composite literal,
// as shown below:
m := map[string]bool{
    "java": false,
    "go":   true,
}