Получатели по указателю
Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 8 из 68.
В то время как получатели значений работают с копиями structs, получатели-указатели работают напрямую с оригинальным экземпляром struct. Когда вы определяете метод с получателем-указателем, метод может изменять исходные данные, так как он получает указатель на struct, а не копию.
Чтобы создать получатель-указатель, добавьте звездочку * перед именем типа в объявлении получателя:
type Person struct {
Name string
Age int
}
func (p *Person) haveBirthday() {
p.Age++ // Это изменяет исходную структуру
}В этом примере (p *Person) является указателем-получателем (pointer receiver). Когда вы вызываете метод haveBirthday для экземпляра Person, метод получает указатель на исходную структуру. Любые изменения, внесенные в поля структуры через этот указатель, окончательно изменят исходные данные.
Указатели-получатели необходимы, когда вашим методам нужно обновлять поля структуры, что делает их идеальными для операций, изменяющих состояние ваших данных.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Задание
ЛегкоВ этом испытании вы попрактикуетесь в создании методов с получателями-указателями (pointer receivers), создав простую систему банковских счетов. Вы создадите структуру Account и определите методы, которые могут изменять баланс счета, используя получатели-указатели.
Вы получите три входных значения:
- Строка, представляющая имя владельца счета (например,
"John Smith") - Строка, представляющая начальный баланс счета (например,
"1000.50") - Строка, представляющая сумму транзакции (например,
"250.75")
Ваша задача:
- Определить структуру
Accountс двумя полями:Name(string) иBalance(float64) - Создать метод с именем
depositс получателем-указателем, который добавляет указанную сумму к балансу счета - Создать метод с именем
withdrawс получателем-указателем, который вычитает указанную сумму из баланса счета - Создать метод с именем
displayBalanceс получателем-значением, который выводит информацию о счете в формате:"Account: [name], Balance: $[balance]" - Обработать входные данные для создания экземпляра
Account - Вызвать
displayBalanceдля отображения начального баланса - Вызвать
depositс суммой транзакции - Вызвать
displayBalanceдля отображения баланса после пополнения - Вызвать
withdrawс суммой транзакции - Вызвать
displayBalanceдля отображения итогового баланса
Баланс должен отображаться с точностью до двух знаков после запятой. Это испытание демонстрирует, как получатели-указатели позволяют методам изменять исходные данные структуры, в отличие от получателей-значений, которые работают с копиями.
Шпаргалка
Указатели-получатели работают напрямую с оригинальным экземпляром структуры, получая указатель на структуру, а не её копию. Это позволяет методам изменять исходные данные.
Чтобы создать указатель-получатель, добавьте звёздочку * перед именем типа в объявлении получателя:
type Person struct {
Name string
Age int
}
func (p *Person) haveBirthday() {
p.Age++ // Это изменяет оригинальную структуру
}Используйте указатели-получатели, когда вашим методам нужно обновить поля структуры, что делает их идеальными для операций, изменяющих состояние ваших данных.
Попробуйте сами
package main
import (
"fmt"
"strconv"
)
// TODO: Определите здесь структуру Account
// TODO: Определите здесь метод deposit с получателем-указателем (pointer receiver)
// TODO: Определите здесь метод withdraw с получателем-указателем (pointer receiver)
// TODO: Определите здесь метод displayBalance с получателем-значением (value receiver)
func main() {
// Чтение входных данных
var name string
var initialBalanceStr string
var transactionAmountStr string
fmt.Scanln(&name)
fmt.Scanln(&initialBalanceStr)
fmt.Scanln(&transactionAmountStr)
// Преобразование строковых входных данных в соответствующие типы
initialBalance, _ := strconv.ParseFloat(initialBalanceStr, 64)
transactionAmount, _ := strconv.ParseFloat(transactionAmountStr, 64)
// TODO: Создайте экземпляр Account
// TODO: Отобразите начальный баланс, выполните пополнение, отобразите баланс, выполните снятие, отобразите итоговый баланс
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком выполнения
Switch с использованием `fallthrough`Выход из вложенных цикловПродолжение конкретного циклаОператор `goto`Итоги: Продвинутое управление циклами4Проект: Простой список задач
Настройка проектаДобавление задачи2Структуры и методы
Определение методов для структурПолучатели по значениюПолучатели по указателюВыбор типа получателяМетоды против функцийИтоги: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картИтоги: счетчик частоты слов3Интерфейсы (Основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование интерфейсных типовПустой интерфейсУтверждение типаПереключатель типовИтоги: Фигуры и поведение