Funkcja ToString () w Go

96

strings.JoinFunkcja przyjmuje kromki tylko ciągi:

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

Ale byłoby miło móc przekazywać dowolne obiekty, które implementują ToString()funkcję.

type ToStringConverter interface {
    ToString() string
}

Czy jest coś takiego w Go, czy muszę udekorować istniejące typy, takie jak intmetody ToString i napisać otokę strings.Join?

func Join(a []ToStringConverter, sep string) string
demon
źródło
7
Zauważ, że taki interfejs już istnieje: golang.org/pkg/fmt/#Stringer
Denys Séguret
@daemon Nie widzę potrzeby stosowania tego duplikatu. Obecne pytanie było moim zdaniem dość jasne, a fakt, że nie było prawdziwej (lub pełnej) odpowiedzi, nie oznacza, że ​​trzeba pytać ponownie.
Denys Séguret

Odpowiedzi:

183

Dołącz String() stringmetodę do dowolnego nazwanego typu i ciesz się dowolną niestandardową funkcją „ToString”:

package main

import "fmt"

type bin int

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

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

Plac zabaw: http://play.golang.org/p/Azql7_pDAA


Wynik

101010
zzzz
źródło
1
Masz rację, chociaż odpowiedź nie oznacza, że ​​konwersja jest jedyną opcją. Punkt znajduje się w metodzie String () dołączonej do typu. Gdziekolwiek fmt. * Znajdzie tę dołączoną metodę, używa jej do uzyskania reprezentacji łańcuchowej tego typu.
zzzz
2
dodanie bin(42).String()jako innego przykładu będzie lepsze dla odpowiedzi.
Thellimist
UWAGA: functon Error() stringma wyższy priorytet niżString() string
Geln Yang
1
Innymi słowy, zaimplementuj Stringerinterfejs: golang.org/pkg/fmt/#Stringer
tothemario
18

Kiedy masz własną struct, możesz mieć własną funkcję konwersji na ciąg .

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]
}
Rio
źródło
4

Kolejny przykład ze strukturą:

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)
}

Zachowaj ostrożność podczas korzystania z niego,
konkatenacja z '+' nie kompiluje się:

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
lgu
źródło
-7

Wolę coś takiego:

type StringRef []byte

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

…

// rather silly example, but ...
fmt.Printf("foo=%s\n",StringRef("bar"))
JSS
źródło
4
Nie potrzebujesz tego, co bezużyteczne :(tj. Po prostu string(s)). Ponadto, jeśli bjest []bytewtedy string(b)znacznie prostszy, a następnie twój StringRef(b).String(). Wreszcie, twój przykład jest bezcelowy, ponieważ %s(w przeciwieństwie %v) już wypisuje []byteargumenty jako łańcuchy bez potencjalnej kopii, która string(b)zwykle to robi.
Dave C