Go-фича: new(expr)
Часть серии Принято! В ней простыми словами объясняются новые фичи Go.
Использовать встроенную функцию new для выражений.
Версия 1.26 • Язык • Важно
Что
Раньше new можно было использовать только с типами:
p1 := new(int)
fmt.Println(*p1)
// 0
А теперь можно и с выражениями:
// Указатель на переменную типа int со значением 42.
p := new(42)
fmt.Println(*p)
// 42
Если аргумент expr — это выражение типа T, то new(expr) аллоцирует переменную типа T (то есть выделяет под нее память), инициализирует ее значением expr и возвращает ее адрес, то есть значение типа *T.
Зачем
Есть простой способ создать указатель на составной литерал:
type Person struct { name string }
p := &Person{name: "alice"}
Но нет простого способа создать указатель на значение простого типа:
n := 42
p := &n
Теперь это исправят.
Подробности
Обновить раздел Allocation в спецификации языка следующим образом (далее перевод с английского):
Выделение памяти
Встроенная функция new создает новую переменную, инициализирует ее и возвращает указатель на нее. Она принимает один аргумент — это может быть выражение или тип.
➀ Если аргумент expr — это выражение типа T или нетипизированная константа, у которой тип по умолчанию — T, то new(expr) выделяет переменную типа T, инициализирует ее значением expr и возвращает ее адрес, то есть значение типа *T.
➁ Если аргумент — это тип T, то new(T) выделяет переменную, инициализированную нулевым значением типа T.
Например, new(123) и new(int) оба возвращают указатель на новую переменную типа int. Значение первой переменной — 123, второй — 0.
➀ — это новая фича, ➁ уже работает как описано.
Примеры
Указатель на простой тип:
// go 1.25
n := 42
p1 := &n
fmt.Println(*p1)
s := "go"
p2 := &s
fmt.Println(*p2)
42
go
// go 1.26
p1 := new(42)
fmt.Println(*p1)
s := "go"
p2 := new(s)
fmt.Println(*p2)
42
go
Указатель на составное значение:
// go 1.25
s := []int{11, 12, 13}
p1 := &s
fmt.Println(*p1)
type Person struct{ name string }
p2 := &Person{name: "alice"}
fmt.Println(*p2)
[11 12 13]
{alice}
// go 1.26
p1 := new([]int{11, 12, 13})
fmt.Println(*p1)
type Person struct{ name string }
p2 := new(Person{name: "alice"})
fmt.Println(*p2)
[11 12 13]
{alice}
Указатель на результат вызова функции:
// go 1.25
f := func() string { return "go" }
v := f()
p := &v
fmt.Println(*p)
go
// go 1.26
f := func() string { return "go" }
p := new(f())
fmt.Println(*p)
go
Передавать nil по-прежнему нельзя:
// go 1.25 and go 1.26
p := new(nil)
// compilation error
Ссылки
𝗣 45624 • 𝗖𝗟 704935, 704737, 704955, 705157
★ Подписывайтесь на канал и проходите курсы.