Получатели-указатели и получатели-значения
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 8 из 107.
Методы могут иметь либо получатель значения, либо получатель-указатель. Получатель значения работает с копией структуры. Получатель-указатель работает с оригинальной структурой и может изменять её поля.
Приемник значения — работает с копией
type Counter struct {
Count int
}
func (c Counter) GetCount() int {
return c.Count
}
// Это НЕ изменяет оригинал
func (c Counter) IncrementWrong() {
c.Count++ // Изменяет только копию!
}Указатель-получатель — изменяет оригинал
// Это ДЕЙСТВИТЕЛЬНО изменяет оригинал
func (c *Counter) Increment() {
c.Count++
}
func (c *Counter) Reset() {
c.Count = 0
}Использование обоих вместе
func main() {
counter := Counter{Count: 0}
counter.Increment()
counter.Increment()
fmt.Println(counter.GetCount()) // Вывод: 2
counter.Reset()
fmt.Println(counter.GetCount()) // Вывод: 0
}Используйте получатель значения, когда метод только считывает данные. Используйте указатель-получатель (*StructName), когда методу необходимо изменить поля структуры. Go автоматически обрабатывает получение указателя и разыменование — вы вызываете оба типа методов одинаково.
Задание
СреднеДобавьте методы к структуре Wallet, используя правильные типы получателей:
GetBalance— получатель по значению, возвращает текущий балансDeposit— получатель по указателю, добавляет сумму к балансуWithdraw— получатель по указателю, вычитает сумму только при наличии достаточного количества средств
Шпаргалка
Методы могут иметь либо получатель значения, либо получатель-указатель. Получатель значения работает с копией структуры. Получатель-указатель работает с оригинальной структурой и может изменять её поля.
Получатель значения — работает с копией:
type Counter struct {
Count int
}
func (c Counter) GetCount() int {
return c.Count
}Получатель-указатель — изменяет оригинал:
func (c *Counter) Increment() {
c.Count++
}Используйте получатель значения, когда метод только считывает данные. Используйте получатель-указатель (*StructName), когда методу необходимо изменить поля структуры.
Попробуйте сами
package main
import "fmt"
func main() {
var balance, deposit, withdraw float64
fmt.Scan(&balance, &deposit, &withdraw)
w := Wallet{Balance: balance}
fmt.Printf("Balance: %.2f\n", w.GetBalance())
w.Deposit(deposit)
fmt.Printf("After deposit: %.2f\n", w.GetBalance())
w.Withdraw(withdraw)
fmt.Printf("After withdrawal: %.2f\n", w.GetBalance())
fmt.Printf("Final balance: %.2f\n", w.GetBalance())
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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