Интерфейс fmt.State
Интерфейс fmt.State предоставляет доступ к состоянию форматтера во время выполнения пользовательских операций форматирования. Он используется в методах типа Formatter, передаваясь как первый аргумент в метод Format. Интерфейс позволяет получить информацию о ширине и точности вывода, а также о текущем флаге форматирования.
Синтаксис
type State interface {
Write(b []byte) (n int, err error)
Width() (wid int, ok bool)
Precision() (prec int, ok bool)
Flag(c int) bool
}
Методы интерфейса
Интерфейс fmt.State содержит следующие методы:
-
Write- записывает байты в выходной поток -
Width- возвращает минимальную ширину поля иtrue, если ширина указана -
Precision- возвращает точность иtrue, если точность указана -
Flag- проверяет, установлен ли флаг форматирования
Пример
Давайте реализуем пользовательский тип с поддержкой форматирования через интерфейс fmt.Formatter, который использует fmt.State:
package main
import (
"fmt"
)
type Person struct {
Name string
Age int
}
func (p Person) Format(state fmt.State, verb rune) {
switch verb {
case 's':
state.Write([]byte(p.Name))
case 'd':
fmt.Fprintf(state, "%d", p.Age)
case 'v':
if state.Flag('+') {
fmt.Fprintf(state, "Name: %s, Age: %d", p.Name, p.Age)
} else {
fmt.Fprintf(state, "%s (%d)", p.Name, p.Age)
}
default:
fmt.Fprintf(state, "%%!%c(Person=%s)", verb, p.Name)
}
}
func main() {
p := Person{Name: "Alice", Age: 30}
fmt.Println(p)
fmt.Printf("%+v\n", p)
fmt.Printf("%s\n", p)
fmt.Printf("%d\n", p)
}
Результат выполнения кода:
"Alice (30)"
"Name: Alice, Age: 30"
"Alice"
"30"
Пример
Рассмотрим пример использования методов Width и Precision для управления выводом:
package main
import (
"fmt"
)
type Number struct {
Value float64
}
func (n Number) Format(state fmt.State, verb rune) {
width, hasWidth := state.Width()
prec, hasPrec := state.Precision()
if !hasPrec {
prec = 2
}
if hasWidth {
fmt.Fprintf(state, "%*.*f", width, prec, n.Value)
} else {
fmt.Fprintf(state, "%.*f", prec, n.Value)
}
}
func main() {
num := Number{Value: 3.14159}
fmt.Println(num)
fmt.Printf("%10.3f\n", num)
fmt.Printf("%.1f\n", num)
}
Результат выполнения кода:
"3.14"
" 3.142"
"3.1"
Пример
Давайте создадим тип, который обрабатывает различные флаги форматирования:
package main
import (
"fmt"
)
type Color struct {
Red int
Green int
Blue int
}
func (c Color) Format(state fmt.State, verb rune) {
switch verb {
case 'v':
if state.Flag('#') {
fmt.Fprintf(state, "#%02X%02X%02X", c.Red, c.Green, c.Blue)
} else if state.Flag('+') {
fmt.Fprintf(state, "R:%d G:%d B:%d", c.Red, c.Green, c.Blue)
} else {
fmt.Fprintf(state, "(%d, %d, %d)", c.Red, c.Green, c.Blue)
}
default:
fmt.Fprintf(state, "%%!%c(Color)", verb)
}
}
func main() {
color := Color{Red: 255, Green: 128, Blue: 0}
fmt.Println(color)
fmt.Printf("%+v\n", color)
fmt.Printf("%#v\n", color)
}
Результат выполнения кода:
"(255, 128, 0)"
"R:255 G:128 B:0"
"#FF8000"
Смотрите также
-
интерфейс
fmt.Formatter,
который определяет метод для пользовательского форматирования -
функцию
fmt.Printf,
которая форматирует и выводит данные с использованием спецификаторов -
функцию
fmt.Sprintf,
которая возвращает отформатированную строку -
спецификатор
%v,
который используется для стандартного форматирования значений