Menu

Printf e Sprintf em Golang: guia dos verbos de formato do fmt

Como o pacote fmt do Go imprime e formata valores: Println, Printf, Sprintf e Errorf, a tabela completa de verbos de formato (%v, %+v, %d, %s, %q, %f, %T, %w e mais), largura, precisão e preenchimento.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

O pacote fmt tem três famílias de funções de impressão, e cada família tem as mesmas três variantes:

FunçãoA saída vai paraFormato
Print, Println, Printfsaída padrãopadrão, padrão com espaços e quebra de linha, string de formato
Sprint, Sprintln, Sprintfuma string devolvidaos mesmos três estilos
Fprint, Fprintln, Fprintfqualquer io.Writer (arquivo, buffer, resposta HTTP)os mesmos três estilos
Errorfum error devolvidostring de formato, mais %w para empacotar

Println coloca espaços entre os operandos e uma quebra de linha no final. Printf não acrescenta nada: você mesmo escreve o \n. Print só coloca espaço entre operandos que não são strings, o que surpreende o bastante para a maior parte do código usar Println ou Printf.

Verbos de formato

Gerais

VerboImprimeExemplo de saída
%vo valor em um formato padrão{Ana 31 [admin]}
%+vstructs com os nomes dos campos{Name:Ana Age:31 Tags:[admin]}
%#vsintaxe Go do valormain.User{Name:"Ana", Age:31, Tags:[]string{"admin"}}
%To tipomain.User
%%um sinal de porcentagem literal%

%+v é o verbo para usar na depuração. Um ponteiro para struct é impresso como &{...} em vez de um endereço. Maps são impressos com as chaves ordenadas, então a saída é estável mesmo com a ordem de iteração dos maps sendo aleatória.

Inteiros

VerboSignificadofmt.Sprintf(verb, 255)
%ddecimal255
%bbinário11111111
%ooctal377
%Ooctal com prefixo 0o0o377
%x / %Xhexadecimal, minúsculas ou maiúsculasff / FF
%#xhexadecimal com prefixo 0x0xff
%co caractere com aquele code pointÿ
%qum literal de caractere entre aspas'ÿ'
%Uformato UnicodeU+00FF

Floats

VerboSignificadofmt.Sprintf(verb, 1234.5678)
%fdecimal, 6 casas por padrão1234.567800
%.2fdecimal, 2 casas1234.57
%enotação científica1.234568e+03
%g%e ou %f, o que for mais curto, sem zeros à direita1234.5678
%vo mesmo que %g1234.5678

%.2f arredonda o valor binário exato do float, então fmt.Sprintf("%.2f", 2.675)2.67: o float64 mais próximo de 2.675 fica um pouco abaixo dele. Nunca formate dinheiro a partir de um float; guarde centavos em um inteiro.

Strings e bytes

VerboSignificadofmt.Sprintf(verb, "go\n")
%sa string purago e uma quebra de linha
%qentre aspas duplas, com escapes visíveis"go\n"
%xhexadecimal de cada byte676f0a
% xhexadecimal com espaços67 6f 0a

%s em um []byte imprime como texto; %v imprime os números ([104 105]).

Outros tipos

VerboTipoImprime
%tbooltrue ou false
%pponteiro, slice, map, channel, funco endereço, como 0xc000012345
%werror (só no Errorf)a mensagem do erro, e o empacota

Largura, precisão e preenchimento

Entre o % e o verbo você pode colocar flags, uma largura e uma precisão:

FormaEfeito
%5dlargura 5, alinhado à direita (preenche com espaços à esquerda)
%-5dlargura 5, alinhado à esquerda
%05dpreenche com zeros
%.2f2 dígitos depois do ponto decimal
%8.2flargura 8 e 2 casas decimais
%.3sno máximo 3 caracteres da string
%+dsempre mostra o sinal
%*dlargura tirada do próximo argumento

Repare que %.0f de 2.5 imprime 2: aqui o Go arredonda a metade para o par. Em strings, a largura conta runes, não colunas na tela, então caracteres CJK e emoji ainda podem desalinhar uma tabela. Para colunas alinhadas de texto variável, o text/tabwriter faz a medição por você.

Índices de argumentos

%[n] escolhe um argumento pela posição, o que permite reutilizá-lo:

fmt.Printf("%[2]s %[1]s\n", "world", "hello") // hello world
fmt.Printf("%d %[1]x %[1]b\n", 10)             // 10 a 1010

Errorf e %w

fmt.Errorf monta um error a partir de uma string de formato. Com %w ele também empacota outro erro, então quem chama ainda consegue detectar o original:

Use %w quando quem chama pode precisar verificar a causa, e %v quando você quer escondê-la de propósito. Desde o Go 1.20 uma chamada de Errorf pode ter vários verbos %w. A página de tratamento de erros aprofunda o empacotamento.

Formatação personalizada com String()

Qualquer tipo com um método String() string controla como %v, %s e Println o exibem:

%d ignora o String() e imprime o número subjacente. Para tipos de erro, o método equivalente é Error() string, que tem prioridade sobre String().

Quando o verbo está errado

O fmt nunca causa panic por um formato ruim. Ele imprime o problema no meio da saída:

fmt.Printf("%d\n", "oops")
fmt.Printf("%d %d\n", 1)
fmt.Printf("%d\n", 1, 2)
%!d(string=oops)
1 %!d(MISSING)
1
%!(EXTRA int=2)

Essa saída costuma chegar à produção porque não derruba nada. O go vet pega os três na hora do build:

./main.go:8:2: fmt.Printf format %d has arg "oops" of wrong type string
./main.go:9:2: fmt.Printf format %d reads arg #2, but call has 1 arg
./main.go:10:2: fmt.Printf call needs 1 arg but has 2 args

Notas de desempenho

O fmt recebe todo argumento como any e inspeciona o tipo em tempo de execução (recorrendo a reflection para structs, slices e maps), o que não é problema para logs e saída, mas pesa em laços apertados. Para converter um único número, strconv.Itoa e strconv.FormatFloat são mais rápidos que Sprintf. Para montar uma string longa em um laço, escreva em um strings.Builder com fmt.Fprintf(&b, ...) em vez de concatenar resultados de Sprintf.

Perguntas frequentes

Qual a diferença entre Println, Printf e Sprintf em Go?

fmt.Println imprime os argumentos separados por espaço, com uma quebra de linha no final. fmt.Printf imprime de acordo com uma string de formato e não acrescenta quebra de linha. fmt.Sprintf formata do mesmo jeito que o Printf, mas devolve o resultado como string em vez de imprimir. fmt.Errorf faz o mesmo e devolve um error.

Como imprimir uma struct com os nomes dos campos em Go?

Use %+v: fmt.Printf("%+v\n", user) imprime {Name:Ana Age:31}. %v imprime só os valores, {Ana 31}, e %#v imprime sintaxe Go incluindo o tipo, main.User{Name:"Ana", Age:31}.

Como formatar um float com 2 casas decimais em Go?

Use %.2f: fmt.Sprintf("%.2f", 3.14159) devolve "3.14". Acrescente uma largura para alinhar colunas, %8.2f, ou um sinal de menos para alinhar à esquerda, %-8.2f. strconv.FormatFloat(f, 'f', 2, 64) dá o mesmo resultado sem string de formato.

O que %w faz no fmt.Errorf?

%w formata um erro como %v e também o empacota, então o novo erro carrega o original. errors.Is e errors.As conseguem então encontrar o erro empacotado: err := fmt.Errorf("load config: %w", os.ErrNotExist) faz errors.Is(err, os.ErrNotExist) ser true. %w só funciona no fmt.Errorf.

Por que minha saída mostra %!d(string=...)?

O verbo não bate com o tipo do argumento, por exemplo %d recebendo uma string. O fmt imprime o problema no meio da saída em vez de causar panic: %!d(string=oops). Argumentos faltando imprimem %!d(MISSING) e argumentos sobrando %!(EXTRA int=2). O go vet pega os três antes de você executar o programa.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR