new() и когда использовать указатели
Выделение памяти с помощью new и распространённые шаблоны работы с указателями
«new() и когда использовать указатели» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Встроенная функция new()
new(T) выделяет обнулённое значение типа T и возвращает *T. Для структур это эквивалентно &T{}:
package main
import "fmt"
func main() {
p := new(int)
fmt.Println(*p) // 0
*p = 42
fmt.Println(*p) // 42
type Point struct{ X, Y int }
pt := new(Point)
fmt.Println(*pt) // {0 0}
}new и &T{}
Для структур форма &T{} более идиоматична и позволяет инициализировать поля. В современном Go функция new используется редко:
package main
import "fmt"
type Config struct{ Port int; Host string }
func main() {
a := new(Config) // zeroed
b := &Config{Port: 8080} // initialized
fmt.Println(a, b)
}Когда возвращать указатель
Возвращайте указатель из конструктора, если:
- Структура хранит состояние, и вызывающие стороны должны совместно использовать один экземпляр
- У структуры есть методы с получателями-указателями (это необходимо для соответствия интерфейсам)
- Структура большая и её копирование затратно
Когда возвращать значение
Возвращайте значение, если:
- Тип небольшой (содержит несколько полей)
- Это неизменяемая конфигурация
- Вы хотите явно показать, что вызывающие стороны получают независимые копии
Пример: time.Time возвращается по значению, несмотря на наличие множества методов.
Указатели в срезах и отображениях
Хранение указателей в коллекциях позволяет совместно изменять данные:
package main
import "fmt"
type User struct{ Name string; Score int }
func main() {
users := []*User{{"Alice", 0}, {"Bob", 0}}
users[0].Score = 100
fmt.Println(users[0]) // &{Alice 100}
}Указатель на примитивный тип для обозначения необязательности
Поле типа *int или *string может иметь нулевое значение, означающее «не задано». Это полезно для JSON с параметром omitempty или необязательных столбцов базы данных:
package main
import "fmt"
type Profile struct {
Name string
Age *int // nil means not provided
}
func main() {
p := Profile{Name: "Alice"}
fmt.Println(p.Age == nil) // true
age := 30
p.Age = &age
fmt.Println(*p.Age) // 30
}Как избежать чрезмерного использования указателей
Чрезмерное использование указателей увеличивает нагрузку на сборщик мусора и снижает локальность кэша. Прежде чем заменять типы-значения указателями только ради производительности, выполните сравнительный тест.
make и new
make инициализирует срезы, отображения и каналы (им требуется внутренняя настройка). new выделяет обнулённую память для любого типа и возвращает указатель. Эти функции предназначены для разных задач:
package main
import "fmt"
func main() {
s := make([]int, 5) // usable slice
m := make(map[string]int) // usable map
p := new(int) // *int pointing to 0
fmt.Println(s, m, *p)
}Шаблон неизменяемого указателя
Возвращайте *T, но документируйте его как неизменяемый: потребители не должны его изменять. Это распространённый подход для объектов конфигурации, совместно используемых горутинами.
Итоги по безопасности указателей
Правила безопасной работы с указателями:
- Всегда проверяйте нулевое значение перед разыменованием
- Не храните указатели на переменные стека дольше времени жизни переменной (анализ выхода переменных за пределы области видимости в Go обрабатывает это)
- Никогда не преобразуйте unsafe.Pointer без крайней необходимости
- Позвольте компилятору управлять размещением в стеке и куче
Быстрая проверка
Что возвращает new(int)?
Итоги: new и указатели
Главные выводы:
new(T)возвращает обнулённый*Tи используется редко; предпочитайте&T{}- Возвращайте значения для небольших и неизменяемых объектов, а указатели — для объектов с состоянием и больших объектов
- Поля типа
*Tпозволяют использовать нулевое значение как признак отсутствия - Не злоупотребляйте указателями — сборка мусора имеет свою цену
Практическое задание
Создайте структуру Settings с полем типа *int для MaxConnections. Напишите функцию, принимающую *Settings и устанавливающую значение по умолчанию только тогда, когда поле имеет нулевое значение.
Изучай Go с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 51
- Уроки
- 203
Часто задаваемые вопросы
Урок «new() и когда использовать указатели» бесплатный?
Да — полный текст урока «new() и когда использовать указатели» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «new() и когда использовать указатели»?
Выделение памяти с помощью new и распространённые шаблоны работы с указателями Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «new() и когда использовать указатели»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Что такое указатели
- Указатели и функции
- Получатели-указатели в методах
- new() и когда использовать указатели