Функція ToString () в Go


95

strings.JoinФункція приймає скибочки тільки рядки:

s := []string{"foo", "bar", "baz"}
fmt.Println(strings.Join(s, ", "))

Але було б непогано мати можливість передавати довільні об’єкти, які реалізують ToString()функцію.

type ToStringConverter interface {
    ToString() string
}

Чи є щось подібне в Go, чи мені доводиться прикрашати існуючі типи, наприклад intметодами ToString, і писати обгортку навколо strings.Join?

func Join(a []ToStringConverter, sep string) string

7
Зверніть увагу, що такий інтерфейс вже існує: golang.org/pkg/fmt/#Stringer
Denys Séguret


@daemon Я не бачу необхідності в цьому дублікаті. На моє переконання, теперішнє запитання було досить чітким, і той факт, що не було реальної (або повної) відповіді, не означає, що вам доведеться запитувати знову.
Denys Séguret

Відповіді:


182

Приєднайте String() stringметод до будь-якого іменованого типу та насолоджуйтесь будь-якою спеціальною функцією "ToString":

package main

import "fmt"

type bin int

func (b bin) String() string {
        return fmt.Sprintf("%b", b)
}

func main() {
        fmt.Println(bin(42))
}

Дитячий майданчик: http://play.golang.org/p/Azql7_pDAA


Вихідні дані

101010

1
Ви маєте рацію, хоча відповідь не означає, що перетворення - це єдиний варіант. Справа в методі String (), приєднаному до типу. У будь-якому місці fmt. * Виявляє, що приєднаний метод використовує його для отримання рядкового подання такого типу.
zzzz

2
додавання bin(42).String()як іншого прикладу буде кращим для відповіді.
Теліміст

ПРИМІТКА: функція Error() stringмає вищий пріоритет, ніжString() string
Geln Yang

1
Іншими словами, реалізуйтеStringer інтерфейс: golang.org/pkg/fmt/#Stringer
tothemario

17

Коли у вас є своє struct, ви можете мати своє функцію перетворення в рядок .

package main

import (
    "fmt"
)

type Color struct {
    Red   int `json:"red"`
    Green int `json:"green"`
    Blue  int `json:"blue"`
}

func (c Color) String() string {
    return fmt.Sprintf("[%d, %d, %d]", c.Red, c.Green, c.Blue)
}

func main() {
    c := Color{Red: 123, Green: 11, Blue: 34}
    fmt.Println(c) //[123, 11, 34]
}

4

Інший приклад зі структурою:

package types

import "fmt"

type MyType struct {
    Id   int    
    Name string
}

func (t MyType) String() string {
    return fmt.Sprintf(
    "[%d : %s]",
    t.Id, 
    t.Name)
}

Будьте обережні, використовуючи його,
конкатенація з '+' не компілюється:

t := types.MyType{ 12, "Blabla" }

fmt.Println(t) // OK
fmt.Printf("t : %s \n", t) // OK
//fmt.Println("t : " + t) // Compiler error !!!
fmt.Println("t : " + t.String()) // OK if calling the function explicitly

-7

Я віддаю перевагу приблизно такому:

type StringRef []byte

func (s StringRef) String() string {
        return string(s[:])
}

…

// rather silly example, but ...
fmt.Printf("foo=%s\n",StringRef("bar"))

4
Вам не потрібно марне :(тобто просто string(s)). Крім того , якщо bє , []byteто string(b)набагато простіше , і тоді ваш StringRef(b).String(). Нарешті, ваш приклад безглуздий, оскільки %s(на відміну від %v) вже друкує []byteаргументи як рядки без потенційної копії, яка string(b)зазвичай це робить.
Dave C
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.