Основы указателей в Go
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 19 из 107.
pointer — это variable, которая хранит memory address другой variable. Вместо того чтобы напрямую хранить значение, она хранит местоположение, где это значение находится в memory. Pointers имеют фундаментальное значение для Go и необходимы для эффективной обработки данных.
Чтобы создать указатель, используйте оператор &, чтобы получить адрес variable, а оператор * — чтобы объявить тип указателя или получить доступ к значению по этому адресу.
x := 42
p := &x // p хранит адрес памяти x
fmt.Println(p) // 0xc000018030 (адрес памяти)
fmt.Println(*p) // 42 (значение по этому адресу)Оператор & означает «address of» и возвращает pointer. Оператор *, когда используется с pointer, означает «значение по адресу» и называется разыменованием. Вы также можете modify original значение через pointer.
x := 10
p := &x
*p = 25 // изменить значение через указатель
fmt.Println(x) // 25 (исходная переменная изменена)Тип указателя записывается как *T, где T — это тип, на который указывает указатель. Указатель на int имеет тип *int.
var p *int // объявляет указатель на int
x := 100
p = &x // p теперь указывает на xНулевое значение pointer — это nil, что означает, что он ни на что не указывает. Попытка разыменовать nil pointer вызывает панику во время выполнения, поэтому всегда проверяй, что pointers инициализированы перед использованием.
Задание
ЛегкоДавайте создадим простой обменник values, демонстрирующий возможности pointers изменять переменные через их memory addresses.
Вы организуете код в двух файлах:
swap.go: Создайте function с именемSwapValues, которая takes два*intpointers в качестве параметров. Эта function должна поменять местами values, на которые указывают эти pointers; after её вызова каждая переменная должна hold original value другой переменной. Function ничего не возвращает; она modify значения напрямую through pointers.main.go: Считайте два целых числа из input, сохраните их в переменных, затем используйте вашу functionSwapValues, чтобы обменять их значения. Выведите оба значения before и after swap, чтобы показать change.
Будут предоставлены следующие входные данные:
- Строка 1: Первое целое число
- Строка 2: Второе целое число
Формат вывода:
Before: a=[first] b=[second]
After: a=[first] b=[second]Например, если даны 10 и 25, ваш вывод должен быть таким:
Before: a=10 b=25
After: a=25 b=10Remember использовать & operator при передаче переменных в function, а operator * внутри function, чтобы получить доступ к фактическим значениям и modify их.
Попробуйте сами
package main
import "fmt"
func main() {
// Считать два целых числа из ввода
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// Вывести значения до обмена
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: Вызвать функцию SwapValues с указателями на a и b
// Не забудьте использовать оператор & для передачи адресов
// Вывести значения после обмена
fmt.Printf("After: a=%d b=%d\n", a, b)
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП в Go
Внешние файлыРабочее пространство и модули GoПакеты и импортыЭкспортируемые и неэкспортируемые именаВведение в ООП в GoСтруктуры как классыОпределение методов структурПолучатели-указатели и получатели-значенияИнициализация структурФункции-конструкторыИтоги — Простой калькулятор4Интерфейсы
Введение в интерфейсыНеявная реализацияИнтерфейс как контрактПустой интерфейс (any)Утверждение типаПереключатель типовКомпозиция интерфейсовИнтерфейсы Stringer и ErrorПовторение: Калькулятор фигур7Инкапсуляция
Экспортируемые и неэкспортируемые поляИнкапсуляция на уровне пакетовГеттеры и сеттерыСокрытие информации в GoИтоги — Записи о студентах10Обобщения (Generics) (Go 1.18+)
Введение в GenericsПараметры типовОграничения типовОбобщенные структурыОбходной путь для обобщенных методовИтоги — Обобщенная коллекция13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy2Глубокое погружение в типы и структуры
Базовые и составные типыОпределение пользовательских типовТеги структурАнонимные структурыВложенные структурыНулевые значения и значения по умолчаниюПовторение — Контактная книга5Композиция вместо наследования
Почему в Go нет наследованияОсновы встраивания структурПродвижение методовВстраивание нескольких структурВстраивание против агрегацииЗатенение встроенных методовИтоги — Иерархия сотрудников8Обработка ошибок и ООП
Интерфейс errorПользовательские типы ошибокОбертывание ошибок (fmt.Errorf)Sentinel-ошибкиerrors.Is() и errors.As()Panic, Defer и RecoverИтоги — Парсер файлов11Стандартная библиотека и ООП
io.Reader и io.Writersort.InterfaceИнтерфейс fmt.Stringerencoding/json со структурамиИнтерфейс http.HandlerПовторение: модели REST API14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикMiddleware как Декоратор3Указатели и память
Основы указателей в GoУказатели на структурыПередача по значению и по ссылкеФункция new()Сборка мусора в GoПовторение: Конструктор связного списка6Полиморфизм в Go
Полиморфизм через интерфейсыУтиная типизация в GoПравила реализации интерфейсовПолиморфные коллекцииВнедрение зависимостейИтоги — Обработчик платежей9Конкурентность и ООП
Основы горутинКаналы и взаимодействиеБуферизованные и небуферизованные каналыОператор selectsync.Mutex и sync.RWMutexsync.WaitGroupПроектирование потокобезопасных структурПовторение — Worker PoolПотренируйтесь самостоятельно: Онлайн-компилятор Go