Интерфейс Stringer
Настраивайте способ печати типов
«Интерфейс Stringer» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Вывод структуры по умолчанию
По умолчанию вывод структуры с помощью %v показывает её исходные поля. Для отладки этого достаточно, но такой вывод не всегда удобен для читателя.
package main
import "fmt"
type Color struct{ R, G, B int }
func main() {
c := Color{255, 0, 0}
fmt.Println(c)
}Интерфейс Stringer
Интерфейс fmt.Stringer содержит один метод:
String() string
Любой тип, определяющий его, управляет своим представлением при выводе.
package main
import "fmt"
type Greeting struct{ Name string }
func (g Greeting) String() string {
return "Hello, " + g.Name
}
func main() {
fmt.Println(Greeting{"Ada"})
}Автоматическое использование
Если у типа есть метод String(), то Println, Printf с %v или %s и другие подобные функции автоматически вызывают его.
package main
import "fmt"
type Greeting struct{ Name string }
func (g Greeting) String() string {
return "Hi " + g.Name
}
func main() {
g := Greeting{"Bob"}
fmt.Printf("%s and %v\n", g, g)
}Форматирование внутри String()
Создайте результат с помощью fmt.Sprintf, чтобы получить аккуратное пользовательское представление.
package main
import "fmt"
type Color struct{ R, G, B int }
func (c Color) String() string {
return fmt.Sprintf("rgb(%d, %d, %d)", c.R, c.G, c.B)
}
func main() {
fmt.Println(Color{255, 128, 0})
}Stringer для именованных типов
Stringer предназначен не только для структур. Любой именованный тип, даже основанный на int, может реализовать его. Это классический шаблон перечисления.
package main
import "fmt"
type Day int
func (d Day) String() string {
names := []string{"Mon", "Tue", "Wed"}
return names[d]
}
func main() {
fmt.Println(Day(1))
}Перечисления с удобным выводом
Объедините iota с Stringer, чтобы константы выводились в виде понятных имён, а не чисел.
package main
import "fmt"
type State int
const (
Idle State = iota
Running
Done
)
func (s State) String() string {
return []string{"Idle", "Running", "Done"}[s]
}
func main() {
fmt.Println(Running)
}Получатель-значение и получатель-указатель
Если String() использует получатель-значение, и значения, и указатели выводятся корректно. При использовании получателя-указателя это происходит только для указателей.
package main
import "fmt"
type Tag struct{ Name string }
func (t Tag) String() string { return "#" + t.Name }
func main() {
t := Tag{"go"}
fmt.Println(t)
fmt.Println(&t)
}Избегайте бесконечной рекурсии
Никогда не вызывайте fmt.Sprintf("%v", t) для того же типа внутри его собственного String(). Это будет бесконечно вызывать String() снова. Форматируйте поля напрямую.
package main
import "fmt"
type Money struct{ Cents int }
func (m Money) String() string {
return fmt.Sprintf("$%.2f", float64(m.Cents)/100)
}
func main() {
fmt.Println(Money{1050})
}Stringer в срезах
При выводе среза значений Stringer каждый элемент форматируется с помощью его метода String().
package main
import "fmt"
type Tag struct{ Name string }
func (t Tag) String() string { return "#" + t.Name }
func main() {
tags := []Tag{{"go"}, {"web"}}
fmt.Println(tags)
}Использование в качестве интерфейса
Вы можете сохранить любой Stringer в переменной типа fmt.Stringer и вызвать String() через интерфейс.
package main
import "fmt"
type City struct{ Name string }
func (c City) String() string { return "City of " + c.Name }
func main() {
var s fmt.Stringer = City{"Oslo"}
fmt.Println(s.String())
}Почему это важно
Реализация Stringer обеспечивает аккуратный вывод Ваших типов везде, где они выводятся или записываются в журнал, без дополнительного кода форматирования в каждом месте вызова.
package main
import "fmt"
type Temp float64
func (t Temp) String() string {
return fmt.Sprintf("%.1f°C", float64(t))
}
func main() {
fmt.Println(Temp(21.5))
}Быстрая проверка
Какой метод должен определить тип, чтобы удовлетворять интерфейсу fmt.Stringer?
Итоги: интерфейс Stringer
Вы научились настраивать вывод:
- Реализуйте
String() string, чтобы удовлетворять интерфейсуfmt.Stringer. fmtавтоматически вызывает его для%vи%s.- Это особенно удобно для перечислений; избегайте рекурсивного использования
%vдля того же типа.
package main
import "fmt"
type Level int
func (l Level) String() string {
return []string{"low", "mid", "high"}[l]
}
func main() {
fmt.Println(Level(2))
}Часто задаваемые вопросы
Урок «Интерфейс Stringer» бесплатный?
Да — полный текст урока «Интерфейс Stringer» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Интерфейс Stringer»?
Настраивайте способ печати типов Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Интерфейс Stringer»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Глаголы Printf
- Sprintf и Fprintf
- Интерфейс Stringer
- Сканирование ввода