Formatar uma sequência Ir sem imprimir?

Existe uma maneira simples de formatar uma string no Go sem imprimir a string?

Eu posso fazer:

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

Mas quero que a string formatada seja retornada em vez de impressa, para que eu possa manipulá-la ainda mais.

Eu também poderia fazer algo como:

 s := "foo: " + bar 

Mas isso se torna difícil de ler quando a string de formato é complexa e complicada quando uma ou muitas das partes não são strings e precisam ser convertidas primeiro, como

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

Eu sou muito novo para ir – meu fundo é em Ruby, onde isso é simples. Existe uma maneira mais simples de fazer isso?

Sprintf

Aqui também é um uso no tutorial, “A Tour of Go”.

 return fmt.Sprintf("at %v, %s", e.When, e.What) 

1. cordas simples

Para cadeias “simples” (normalmente o que se encheckbox em uma linha), a solução mais simples é usar fmt.Sprintf() e amigos ( fmt.Sprint() , fmt.Sprintln() ). Eles são análogos às funções sem a letra S inicial, mas essas variantes Sxxx() retornam o resultado como uma string vez de imprimi-las na saída padrão.

Por exemplo:

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

A variável s será inicializada com o valor:

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

Dica: Se você quiser apenas concatenar valores de diferentes tipos, você pode não precisar usar automaticamente o Sprintf() (que requer uma string de formatação), já que o Sprint() faz exatamente isso. Veja este exemplo:

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

Para concatenar apenas string , você também pode usar strings.Join() onde é possível especificar uma string separação personalizada (a ser colocada entre as cadeias de caracteres a serem strings.Join() ).

Experimente estes no Go Playground .

2. Strings complexas (documentos)

Se a string que você está tentando criar é mais complexa (por exemplo, uma mensagem de e-mail com várias linhas), fmt.Sprintf() se torna menos legível e menos eficiente (especialmente se você tiver que fazer isso muitas vezes).

Para isso, a biblioteca padrão fornece os pacotes text/template e html/template . Esses pacotes implementam modelos controlados por dados para gerar saída textual. html/template é para gerar saída em HTML segura contra injeção de código. Ele fornece a mesma interface do text/template pacote e deve ser usado em vez de text/template sempre que a saída for HTML.

Usar os pacotes de template basicamente requer que você forneça um modelo estático na forma de um valor de string (que pode ser originário de um arquivo, caso em que você fornece apenas o nome do arquivo) que pode conter texto estático e ações que são processadas e executadas quando o mecanismo processa o modelo e gera a saída.

Você pode fornecer parâmetros que são incluídos / substituídos no modelo estático e que podem controlar o processo de geração de saída. Forma típica de tais parâmetros são os valores de struct e map que podem ser nesteds.

Exemplo:

Por exemplo, digamos que você queira gerar mensagens de e-mail semelhantes a esta:

 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 gerar corpos de mensagens de email como este, você pode usar o seguinte modelo estático:

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

E forneça dados como este para executá-lo:

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

Normalmente, a saída dos modelos é gravada em um io.Writer , portanto, se você quiser o resultado como uma string , crie e bytes.Buffer um bytes.Buffer (que implementa o io.Writer ). Executando o template e obtendo o 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() 

Isso resultará na saída esperada:

 Hi Bob! Your account is ready, your user name is: bob92 You have the following roles assigned: dbteam, uiteam, tester 

Experimente no Go Playground .

Observe também que, desde o Go 1.10, uma alternativa mais nova, mais rápida e mais especializada está disponível para o bytes.Buffer que é: strings.Builder . O uso é muito semelhante:

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

Tente este no Go Playground .

Nota: você também pode exibir o resultado de uma execução de modelo se você fornecer os.Stdout como o destino (que também implementa o io.Writer ):

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

Isto irá escrever o resultado diretamente para os.Stdout . Tente isso no Go Playground .

No seu caso, você precisa usar o Sprintf () para string de formato.

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

O Sprintf formata de acordo com um especificador de formato e retorna a string resultante.

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

Sua saída será:

Bom dia, esse é John e eu moro aqui nos últimos 20 anos.

A function fmt.SprintF retorna uma string e você pode formatar a string da mesma forma que faria com fmt.PrintF