Интерфейс fmt.Stringer
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 75 из 107.
Интерфейс fmt.Stringer управляет тем, как отображаются ваши типы при печати. Это один из наиболее часто реализуемых интерфейсов в Go, определённый в пакете fmt:
type Stringer interface {
String() string
}Когда вы передаёте значение в fmt.Println, fmt.Printf с %v или подобные функции, Go проверяет, реализует ли тип Stringer. Если да, Go вызывает String() method, чтобы получить текстовое представление.
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}Без метода String() при печати отображался бы формат структуры по умолчанию: {23.5}. Реализуя Stringer, вы точно контролируете, как ваш тип представляется.
Это особенно полезно для типов, у которых необработанные значения полей не передают смысл достаточно ясно. Тип Duration может отображаться как "2h 30m", вместо того чтобы показывать необработанные наносекунды, а тип User может отображать отформатированное имя вместо всех своих полей.
Задание
ЛегкоДавайте создадим систему учёта времени, которая отображает продолжительность в удобном для пользователя формате! Вы реализуете интерфейс fmt.Stringer, чтобы управлять отображением ваших пользовательских типов при печати.
Вы организуете код в двух файлах:
duration.go: Определите типы, связанные со временем, с пользовательскими строковыми представлениями.Создайте структуру
Duration, которая хранит общее количество минут в виде целого числа. Реализуйте методString(), чтобы при печати значение отображалось в понятном формате, например2h 30mдля 150 минут или0h 45mдля 45 минут. Часы и минуты должны отображаться всегда.Создайте структуру
Taskс полямиName(string) иTime(Duration). Реализуйте для Task методString(), чтобы отображать его в формате[Name]: [duration], где для продолжительности используется её собственный метод String.main.go: Создайте и отобразите tasks вместе с их продолжительностью.Считайте количество tasks, затем для каждой task считайте её имя и продолжительность в минутах. Создайте экземпляры Task и выведите каждый из них напрямую с помощью
fmt.Println: интерфейс Stringer автоматически выполнит форматирование.После вывода всех tasks вычислите и выведите общее время для всех tasks в формате:
Total: [duration]
Будут предоставлены следующие входные данные:
- Строка 1: количество tasks
- Следующие строки: имя Task и минуты (по две строки на каждую task)
Например, для следующих данных:
3
Code Review
90
Meeting
45
Documentation
120Ваш вывод должен быть таким:
Code Review: 1h 30m
Meeting: 0h 45m
Documentation: 2h 0m
Total: 4h 15mА для следующих данных:
2
Design
180
Testing
65Ваш вывод должен быть таким:
Design: 3h 0m
Testing: 1h 5m
Total: 4h 5mРеализовав Stringer, вы обеспечите бесшовную интеграцию своих типов с функциями печати Go. Вместо необработанных полей структуры, таких как {90}, вы получите осмысленный вывод, понятный пользователям.
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Прочитать количество задач
line, _ := reader.ReadString('\n')
numTasks, _ := strconv.Atoi(strings.TrimSpace(line))
// TODO: Создать слайс для хранения задач
// TODO: Отслеживать общее количество минут
for i := 0; i < numTasks; i++ {
// Прочитать название задачи
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// Прочитать длительность задачи в минутах
minutesLine, _ := reader.ReadString('\n')
minutes, _ := strconv.Atoi(strings.TrimSpace(minutesLine))
// TODO: Создать Task с name и Duration
// TODO: Вывести задачу (fmt.Println будет использовать интерфейс Stringer)
// TODO: Добавить minutes к total
_ = name
_ = minutes
}
// TODO: Вывести общую длительность в формате "Total: Xh Ym"
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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