Интерфейс fmt.Formatter
Интерфейс fmt.Formatter предоставляет возможность
определить собственный способ форматирования для пользовательских
типов. Он содержит единственный метод Format,
который вызывается функциями пакета fmt
(например, fmt.Print, fmt.Sprintf и другими)
при выводе значения типа, реализующего этот интерфейс.
Метод Format принимает два параметра:
первый параметр state - это интерфейс fmt.State,
предоставляющий доступ к информации о флагах форматирования и
ширине поля; второй параметр verb - это символ
(например, 'v', 's', 'd'), указывающий, с каким флагом
форматирования было вызвано значение.
Реализуя этот интерфейс, вы можете полностью контролировать текстовое представление ваших типов в зависимости от используемого флага и дополнительных параметров форматирования.
Синтаксис
type Formatter interface {
Format(state fmt.State, verb rune)
}
Пример
Давайте создадим тип Person и реализуем для него
интерфейс fmt.Formatter, чтобы при выводе с
флагом 'v' отображалось полное имя, а с флагом 's' -
только имя:
package main
import (
"fmt"
"io"
)
type Person struct {
Name string
Surname string
}
func (p Person) Format(state fmt.State, verb rune) {
switch verb {
case 'v':
io.WriteString(state, p.Name+" "+p.Surname)
case 's':
io.WriteString(state, p.Name)
default:
io.WriteString(state, fmt.Sprint(p))
}
}
func main() {
p := Person{Name: "John", Surname: "Doe"}
fmt.Printf("%v\n", p)
fmt.Printf("%s\n", p)
}
Результат выполнения кода:
"John Doe"
"John"
Пример
Теперь рассмотрим пример, где форматирование зависит от
дополнительных флагов, таких как ширина поля. Создадим тип
Number, который при выводе с флагом 'd' будет
отображать число с ведущими нулями, если указана ширина:
package main
import (
"fmt"
"io"
)
type Number int
func (n Number) Format(state fmt.State, verb rune) {
if verb == 'd' {
width, hasWidth := state.Width()
if hasWidth && width > 0 {
io.WriteString(state, fmt.Sprintf("%0*d", width, n))
return
}
io.WriteString(state, fmt.Sprintf("%d", n))
return
}
io.WriteString(state, fmt.Sprint(n))
}
func main() {
num := Number(42)
fmt.Printf("%d\n", num)
fmt.Printf("%5d\n", num)
}
Результат выполнения кода:
"42"
"00042"
Пример
В этом примере мы реализуем интерфейс fmt.Formatter
для типа Color, чтобы при выводе с флагом 'v'
отображалось название цвета в цветных скобках, а с флагом 's' -
только название цвета в верхнем регистре:
package main
import (
"fmt"
"io"
"strings"
)
type Color string
func (c Color) Format(state fmt.State, verb rune) {
switch verb {
case 'v':
io.WriteString(state, "["+string(c)+"]")
case 's':
io.WriteString(state, strings.ToUpper(string(c)))
default:
io.WriteString(state, fmt.Sprint(c))
}
}
func main() {
color := Color("red")
fmt.Printf("%v\n", color)
fmt.Printf("%s\n", color)
}
Результат выполнения кода:
"[red]"
"RED"
Смотрите также
-
интерфейс
fmt.Stringer,
который определяет методStringдля строкового представления типа -
интерфейс
fmt.GoStringer,
который определяет методGoStringдля представления типа в формате Go -
интерфейс
fmt.State,
который предоставляет информацию о параметрах форматирования -
функцию
fmt.Printf,
которая используетFormatterдля вывода значений