Menu
Coddy logo textTech

Получатели по указателю

Часть раздела Логика и управление потоком путешествия по 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, метод получает указатель на исходную структуру. Любые изменения, внесенные в поля структуры через этот указатель, окончательно изменят исходные данные.

Указатели-получатели необходимы, когда вашим методам нужно обновлять поля структуры, что делает их идеальными для операций, изменяющих состояние ваших данных.

quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

challenge icon

Задание

Легко

В этом испытании вы попрактикуетесь в создании методов с получателями-указателями (pointer receivers), создав простую систему банковских счетов. Вы создадите структуру Account и определите методы, которые могут изменять баланс счета, используя получатели-указатели.

Вы получите три входных значения:

  • Строка, представляющая имя владельца счета (например, "John Smith")
  • Строка, представляющая начальный баланс счета (например, "1000.50")
  • Строка, представляющая сумму транзакции (например, "250.75")

Ваша задача:

  1. Определить структуру Account с двумя полями: Name (string) и Balance (float64)
  2. Создать метод с именем deposit с получателем-указателем, который добавляет указанную сумму к балансу счета
  3. Создать метод с именем withdraw с получателем-указателем, который вычитает указанную сумму из баланса счета
  4. Создать метод с именем displayBalance с получателем-значением, который выводит информацию о счете в формате: "Account: [name], Balance: $[balance]"
  5. Обработать входные данные для создания экземпляра Account
  6. Вызвать displayBalance для отображения начального баланса
  7. Вызвать deposit с суммой транзакции
  8. Вызвать displayBalance для отображения баланса после пополнения
  9. Вызвать withdraw с суммой транзакции
  10. Вызвать 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: Отобразите начальный баланс, выполните пополнение, отобразите баланс, выполните снятие, отобразите итоговый баланс
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и управление потоком