Formatować ciąg Go bez drukowania?

Czy istnieje prosty sposób sformatowania łańcucha w Go bez drukowania łańcucha?

Potrafię:

bar := "bar"
fmt.Printf("foo: %s", bar)

Ale chcę, aby sformatowany łańcuch został zwrócony, a nie wydrukowany, aby móc dalej nim manipulować.

Mógłbym też zrobić coś takiego:

s := "foo: " + bar

Ale staje się to trudne do odczytania, gdy ciąg formatowania jest złożony i kłopotliwe, gdy jedna lub wiele części nie jest ciągami i musi być przekonwertowana jako pierwsza, jak

i := 25
s := "foo: " + strconv.Itoa(i)

Jestem bardzo Nowy, aby przejść - moje pochodzenie jest w Ruby, gdzie jest to proste. Czy jest na to prostszy sposób?

Author: Tim Cooper, 2012-06-20

4 answers

 304
Author: Sonia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-10 05:31:38

1. Struny proste

Dla" prostych " ciągów (typowo tego, co pasuje do linii) najprostszym rozwiązaniem jest użycie fmt.Sprintf() i przyjaciele (fmt.Sprint(), fmt.Sprintln()). Są one analogiczne do funkcji bez litery starter S, ale te warianty Sxxx() zwracają wynik jako string zamiast drukować je na standardowym wyjściu.

Na przykład:

s := fmt.Sprintf("Hi, my name is %s and I'm %d years old.", "Bob", 23)

Zmienna s zostanie zainicjowana wartość:

Hi, my name is Bob and I'm 23 years old.

Wskazówka: jeśli chcesz po prostu połączyć wartości różnych typów, może nie być konieczne automatyczne użycie Sprintf() (która wymaga ciągu formatującego), ponieważ Sprint() robi dokładnie to. Zobacz ten przykład:

i := 23
s := fmt.Sprint("[age:", i, "]") // s will be "[age:23]"

Do łączenia tylko strings, można również użyć strings.Join() gdzie można określić niestandardowy separator string (który ma być umieszczony pomiędzy ciągami znaków do połączenia).

Spróbuj tego na Go Playground .

2. Struny złożone (dokumenty)

Jeśli ciąg znaków, który próbujesz utworzyć, jest bardziej złożony (np. wielowierszowa wiadomość e-mail), fmt.Sprintf() staje się mniej czytelny i mniej wydajny (zwłaszcza jeśli musisz to robić wiele razy).

W tym celu biblioteka standardowa udostępnia Pakiety text/template oraz html/template. Pakiety te implementują szablony oparte na danych do generowania danych wyjściowych. {[24] } jest do generowania wyjścia HTML bezpiecznego przed wtryskiem kodu. Zapewnia ten sam interfejs, co pakiet text/template i powinien być używany zamiast text/template, gdy wyjściem jest HTML.

Używanie pakietów template zasadniczo wymaga podania statycznego szablonu w postaci wartości string (która może pochodzić z pliku, w którym to przypadku podajesz tylko nazwę pliku), który może zawierać statyczny tekst oraz akcje, które są przetwarzane i wykonywane, gdy silnik przetwarza szablon i generuje wyjście.

Możesz podać parametry, które są zawarte/podstawione w szablonie statycznym i które mogą sterować procesem generowania danych wyjściowych. Typową formą takich parametrów są wartości struct s i map, które mogą być zagnieżdżone.

Przykład:

Na przykład powiedzmy, że chcesz generować wiadomości e-mail, które wyglądają tak:

Hi [name]!

Your account is ready, your user name is: [user-name]

You have the following roles assigned:
[role#1], [role#2], ... [role#n]

Aby wygenerować treść wiadomości e-mail w ten sposób, możesz użyć następującego statycznego szablonu:

const emailTmpl = `Hi {{.Name}}!

Your account is ready, your user name is: {{.UserName}}

You have the following roles assigned:
{{range $i, $r := .Roles}}{{if ne $i 0}}, {{end}}{{.}}{{end}}
`

I podaj takie dane do jego wykonania:

data := map[string]interface{}{
    "Name":     "Bob",
    "UserName": "bob92",
    "Roles":    []string{"dbteam", "uiteam", "tester"},
}

Normalnie wyjście z szablony są pisane do io.Writer, więc jeśli chcesz, aby wynik był string, Utwórz i napisz do bytes.Buffer (która implementuje io.Writer). Wykonanie szablonu i uzyskanie wyniku jako string:

t := template.Must(template.New("email").Parse(emailTmpl))
buf := &bytes.Buffer{}
if err := t.Execute(buf, data); err != nil {
    panic(err)
}
s := buf.String()

Spowoduje to oczekiwany wynik:

Hi Bob!

Your account is ready, your user name is: bob92

You have the following roles assigned:
dbteam, uiteam, tester

Spróbuj na Go Playground .

Należy również zauważyć, że od wersji Go 1.10 dostępna jest nowsza, szybsza, bardziej wyspecjalizowana alternatywa dla bytes.Buffer, która jest: strings.Builder. Użycie jest bardzo podobne:

builder := &strings.Builder{}
if err := t.Execute(builder, data); err != nil {
    panic(err)
}
s := builder.String()

Spróbuj tego na Go Playground .

Uwaga: Możesz również wyświetlić wynik wykonania szablonu, jeśli podasz os.Stdout jako cel (który również implementuje io.Writer):

t := template.Must(template.New("email").Parse(emailTmpl))
if err := t.Execute(os.Stdout, data); err != nil {
    panic(err)
}

Wynik zostanie zapisany bezpośrednio do os.Stdout. Spróbuj tego na Go Playground .

 135
Author: icza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-21 06:05:26

Fmt.Funkcja SprintF zwraca łańcuch znaków i można go sformatować w taki sam sposób, jak w przypadku fmt.PrintF

 0
Author: Mo-Gang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 06:47:31

W Twoim przypadku, musisz użyć Sprintf () dla formatu string.

func Sprintf(format string, a ...interface{}) string

Sprintf formatuje zgodnie ze specyfikacją formatu i zwraca wynikowy ciąg znaków.

s := fmt.Sprintf("Good Morning, This is %s and I'm living here from last %d years ", "John", 20)

Twój wynik będzie:

Dzień dobry, Tu John i mieszkam tu od 20 lat.
 -1
Author: Kabeer Shaikh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 03:14:16