Formatear una cadena de Go sin imprimir?

Jun 28, 2021
admin

Cadenas simples

Para cadenas «simples» (típicamente lo que cabe en una línea) la solución más sencilla es usar fmt.Sprintf() y amigos (fmt.Sprint(), fmt.Sprintln()). Son análogas a las funciones sin la letra inicial S, pero estas variantes de Sxxx() devuelven el resultado como un string en lugar de imprimirlo en 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 sólo quiere concatenar valores de diferentes tipos, puede que no necesite utilizar automáticamente Sprintf() (que requiere una cadena de formato) ya que Sprint() hace exactamente esto. Vea este ejemplo:

i := 23s := fmt.Sprint("") // s will be ""

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

Pruebe estos en el Go Playground.

Cadenas complejas (documentos)

Si la cadena que intentas 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 tienes que hacer esto muchas veces).

Para esto la biblioteca estándar proporciona los paquetes text/template y html/template. Estos paquetes implementan plantillas basadas en datos para generar una salida textual. html/template es para generar una salida HTML segura contra la inyección de código. Proporciona la misma interfaz que el paquete text/template y debería usarse en lugar de text/template siempre que la salida sea HTML.

Usar los paquetes template requiere básicamente proporcionar una plantilla estática en forma de valor string (que puede provenir de un archivo, en cuyo caso sólo se 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 pueden controlar el proceso de generación de la salida. La forma típica de tales parámetros son los valores structs y map que pueden estar anidados.

Ejemplo:

Por ejemplo, digamos que quiere generar mensajes de correo electrónico con el siguiente aspecto:

Hi !Your account is ready, your user name is: You have the following roles assigned:, , ... 

Para generar cuerpos de mensajes de correo electrónico como este, podría utilizar 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 $i}}, {{end}}{{.}}{{end}}`

Y proporcionar datos como estos para ejecutarla:

data := mapinterface{}{ "Name": "Bob", "UserName": "bob92", "Roles": string{"dbteam", "uiteam", "tester"},}

Normalmente la salida de las plantillas se escribe en un io.Writer, así que si quieres el resultado como un string, crea y escribe en un bytes.Buffer (que implementa io.Writer). Ejecutando la plantilla y obteniendo 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: bob92You have the following roles assigned:dbteam, uiteam, tester

Pruébalo en el Go Playground.

También ten 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 esto en el Go Playground.

Nota: también puedes mostrar el resultado de la ejecución de una plantilla si proporcionas os.Stdout como objetivo (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 en os.Stdout. Pruebe esto en el Go Playground.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.