Интерфейс fmt.Stringer
Интерфейс fmt.Stringer определен в пакете fmt и позволяет типам управлять тем,
как они представляются в виде строки. Когда тип реализует этот интерфейс,
функции пакета fmt, такие как fmt.Println, fmt.Sprintf
и другие, будут использовать метод String для получения строкового
представления значения.
Синтаксис
Интерфейс fmt.Stringer объявлен следующим образом:
type Stringer interface {
String() string
}
Любой тип, который определяет метод String с сигнатурой
func String() string, автоматически реализует этот интерфейс.
Пример
Давайте создадим пользовательский тип Person и реализуем для него
интерфейс fmt.Stringer:
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("Person{Name: %s, Age: %d}", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 30}
fmt.Println(p)
}
Результат выполнения кода:
Person{Name: Alice, Age: 30}
Пример
Теперь рассмотрим тип IPAddress, который хранит IP-адрес как массив байтов
и возвращает его строковое представление:
package main
import "fmt"
type IPAddress [4]byte
func (ip IPAddress) String() string {
return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
}
func main() {
ip := IPAddress{192, 168, 1, 1}
fmt.Println(ip)
}
Результат выполнения кода:
192.168.1.1
Пример
Важно отметить, что если метод String определен с указателем в качестве
получателя, то интерфейс будет реализован только для указателей на тип,
а не для самих значений:
package main
import "fmt"
type User struct {
ID int
Name string
}
func (u *User) String() string {
return fmt.Sprintf("User{ID: %d, Name: %s}", u.ID, u.Name)
}
func main() {
u1 := &User{ID: 1, Name: "Bob"} // указатель
fmt.Println(u1)
u2 := User{ID: 2, Name: "Charlie"} // значение
fmt.Println(u2)
}
Результат выполнения кода:
User{ID: 1, Name: Bob}
{2 Charlie}
Второй вызов выводит стандартное представление структуры, так как
интерфейс fmt.Stringer не реализован для значений типа User,
а только для указателей на них.
Пример
Использование интерфейса fmt.Stringer с функциями пакета fmt
для форматированного вывода:
package main
import "fmt"
type Point struct {
X int
Y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}
func main() {
p1 := Point{X: 10, Y: 20}
p2 := Point{X: 5, Y: 15}
fmt.Printf("Point 1: %v\n", p1)
fmt.Printf("Point 2: %v\n", p2)
fmt.Printf("Combined: %v and %v\n", p1, p2)
}
Результат выполнения кода:
Point 1: (10, 20)
Point 2: (5, 15)
Combined: (10, 20) and (5, 15)
Смотрите также
-
интерфейс
interface,
который определяет базовое понятие интерфейсов в Go -
интерфейс
error,
который используется для представления ошибок в виде строки -
концепцию
implementation,
описывающую реализацию интерфейсов в Go -
конструкцию
type assertion,
которая позволяет извлекать значение конкретного типа из интерфейса