[string] Golang: форматировать строку без печати?


Answers

1. Простые строки

Для «простых» строк (как правило, это то, что подходит в строке) самым простым решением является использование fmt.Sprintf() и друзей ( fmt.Sprint() , fmt.Sprintln() ). Они аналогичны функциям без буквы S стартера, но эти Sxxx() возвращают результат как string а не печатают их на стандартный вывод.

Например:

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

Переменная s будет инициализирована значением:

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

Совет. Если вы просто хотите конкатенировать значения разных типов, вам не обязательно автоматически использовать Sprintf() (для чего требуется строка формата), поскольку Sprint() делает именно это. См. Этот пример:

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

Для конкатенации только string s вы также можете использовать strings.Join() где вы можете указать пользовательскую string разделителя (для размещения между строками для присоединения).

Попробуйте это на игровой площадке Go .

2. Комплексные строки (документы)

Если строка, которую вы пытаетесь создать, более сложна (например, многострочное сообщение электронной почты), fmt.Sprintf() становится менее читаемым и менее эффективным (особенно если вам нужно делать это много раз).

Для этого стандартная библиотека предоставляет пакеты text/template и html/template . Эти пакеты реализуют управляемые данными шаблоны для генерации текстового вывода. html/template предназначен для создания HTML-вывода, безопасного для ввода кода. Он предоставляет тот же интерфейс, что и text/template пакета, и должен использоваться вместо text/template всякий раз, когда вывод является HTML.

Использование пакетов template основном требует предоставления статического шаблона в виде string значения (которое может происходить из файла, в этом случае вы указываете только имя файла), которое может содержать статический текст, а также действия, которые обрабатываются и выполняются когда двигатель обрабатывает шаблон и генерирует выход.

Вы можете предоставить параметры, которые включены / заменены в статическом шаблоне и которые могут управлять процессом генерации вывода. Типичной формой таких параметров являются struct s и значения map которые могут быть вложенными.

Пример:

Например, предположим, что вы хотите генерировать сообщения электронной почты, которые выглядят следующим образом:

Hi [name]!

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

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

Чтобы создать такие тела сообщений электронной почты, вы можете использовать следующий статический шаблон:

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

И предоставить такие данные для его выполнения:

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

Обычно вывод шаблонов записывается в io.Writer , поэтому, если вы хотите получить результат в виде string , создайте и напишите в bytes.Buffer (который реализует io.Writer ). Выполнение шаблона и получение результата в виде 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()

Это приведет к ожидаемому результату:

Hi Bob!

Your account is ready, your user name is: bob92

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

Попробуйте на игровой площадке Go .

Также обратите внимание, что начиная с Go 1.10 для bytes.Buffer доступна более новая, более быстрая и более специализированная альтернатива: strings.Builder . Использование очень похоже:

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

Попробуйте это на игровой площадке Go .

Примечание. Вы также можете отобразить результат выполнения шаблона, если вы os.Stdout как цель (которая также реализует io.Writer ):

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

Это будет записывать результат непосредственно в os.Stdout . Попробуйте это на игровой площадке Go .

Question

Есть ли простой способ форматирования строки в Go без печати строки?

Я могу сделать:

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

Но я хочу, чтобы отформатированная строка возвращалась, а не печаталась, поэтому я могу манипулировать ею дальше.

Я мог бы также сделать что-то вроде:

s := "foo: " + bar

Но это становится трудно читать, когда строка формата сложна и громоздка, когда одна или многие части не являются строками и должны быть сначала преобразованы, например

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

Я очень новичок в Go - мой опыт в Ruby, где это просто. Есть ли более простой способ сделать это?




Related