¿Formatear una cadena Go sin imprimir?


¿Hay una forma sencilla de formatear una cadena en Go sin imprimirla?

Puedo hacer:

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

Pero quiero que se devuelva la cadena formateada en lugar de imprimirla para poder manipularla aún más.

También podría hacer algo como:

s := "foo: " + bar

Pero esto se vuelve difícil de leer cuando la cadena de formato es compleja, y engorroso cuando una o muchas de las partes no son cadenas y tienen que ser convertidas primero, como

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

Soy muy nuevo para Ir-mis antecedentes está en Ruby, donde esto es sencillo. ¿Hay una forma más sencilla de hacer esto?

Author: Tim Cooper, 2012-06-20

4 answers

Sprintf

Aquí también es un uso de él en el tutorial, "A Tour of Go."

return fmt.Sprintf("at %v, %s", e.When, e.What)
 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-10 05:31:38

1. Cadenas simples

Para cadenas" simples " (típicamente lo que encaja en una línea) la solución más simple es usar fmt.Sprintf() y amigos (fmt.Sprint(), fmt.Sprintln()). Estas son análogas a las funciones sin la letra starter S, pero estas variantes Sxxx() devuelven el resultado como un string en lugar de imprimirlas a la salida estándar.

Por ejemplo:

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

La variable s se inicializará con el valor:

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

Consejo: Si solo desea concatenar valores de diferentes tipos, es posible que no necesite usar automáticamente Sprintf() (lo que requiere una cadena de formato), ya que Sprint() hace exactamente esto. Ver este ejemplo:

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

Para concatenar solo string s, también puede usar strings.Join() donde puede especificar un separador personalizado string (que se colocará entre las cadenas a unir).

Pruébalos en el Go Playground .

2. Cadenas complejas (documentos)

Si la cadena que está tratando de crear es más compleja (por ejemplo, un mensaje de correo electrónico de varias líneas), fmt.Sprintf() se vuelve menos legible y menos eficiente (especialmente si tiene que hacer esto muchas veces).

Para ello la biblioteca estándar proporciona los paquetes text/template y html/template. Estos paquetes implementan plantillas basadas en datos para generar resultados textuales. html/template es para generar salida HTML segura contra la inyección de código. Proporciona la misma interfaz paquete text/template y debe usarse en lugar de text/template siempre que la salida sea HTML.

Usar los paquetes template básicamente requiere que proporcione una plantilla estática en forma de un valor string (que puede originarse de un archivo, en cuyo caso solo proporciona el nombre del archivo) que puede contener texto estático, y acciones que se procesan y ejecutan cuando el motor procesa la plantilla y genera la salida.

Puede proporcionar parámetros que se incluyen / sustituyen en la plantilla estática y que puede controlar el proceso de generación de salida. La forma típica de tales parámetros son struct s y map valores que pueden ser anidados.

Ejemplo:

Por ejemplo, supongamos que desea generar mensajes de correo electrónico que se vean así:

Hi [name]!

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

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

Para generar cuerpos de mensajes de correo electrónico como este, puede usar la siguiente plantilla estática:

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

Y proporcionar datos como este para ejecutarlo:

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

Normalmente salida de las plantillas se escriben en un io.Writer, así que si quieres el resultado como un string, crear y escribir en un bytes.Buffer (que implementa io.Writer). Ejecutar la plantilla y obtener el resultado como 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()

Esto dará como resultado la salida esperada:

Hi Bob!

Your account is ready, your user name is: bob92

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

Pruébalo en el Go Playground.

También tenga en cuenta que desde Go 1.10, una alternativa más nueva, más rápida y más especializada está disponible para bytes.Buffer que es: strings.Builder. El uso es muy similar:

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

Prueba este en el Go Playground .

Nota: también puede mostrar el resultado de una ejecución de plantilla si proporciona os.Stdout como destino (que también implementa io.Writer):

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

Esto escribirá el resultado directamente a os.Stdout. Prueba esto en el 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-21 06:05:26

Fmt.La función SprintF devuelve una cadena y puede formatear la cadena de la misma manera que lo haría con 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-20 06:47:31

En tu caso, necesitas usar Sprintf() para format string.

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

Sprintf formatea de acuerdo con un especificador de formato y devuelve la cadena resultante.

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

Su salida será:

Buenos días, soy John y vivo aquí desde hace 20 años.

 -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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-23 03:14:16