- Golang – 01. Introdução
- Golang – 02. Tipos Básicos
- Golang – 03. Structs e Funções e Métodos
- Golang – 04. Estruturas de Controle
- Golang – 05. Gerenciando Pacotes
- Golang – 06. Biblioteca Padrão I – fmt e strings
- Golang – 07. Biblioteca Padrão II – os, os/exec e os/user
- Golang – 08. Interface
- Golang – 09. Goroutines – Concorrência e Paralelismo
- Golang – 10. Goroutines – Canais
- Golang – 11. Pacotes e Documentação no Go
Índice
- 1. Pacote fmt
- 1.1. Códigos de Formatação
- 1.2. Funções Print, Printf e Println
- 1.2.1. Retorno das Funções Print
- 1.3. Funções Scan, Scanf e Scanln
- 1.3.1. Separadores Espaço e Quebra de Linha
- 1.3.2. Retorno das Funções Scan
- 1.4. Funções Sprint, Sprintln e Sprintf
- 1.5. Função Errorf
- 1.6. Como ler Strings com espaços no fmt?
- 2. Pacote Strings
- 2.1. Função strings.Compare
- 2.2. Funções Contains, ContainsAny e ContainsRune
- 2.2.1. Função Contains
- 2.2.2. Função ContainsAny
- 2.2.3. Função ContainsRune
- 2.3. Função Count
- 2.4. Função Cut
- 2.5. Funções Index, IndexAny, IndexByte e IndexRune
- 2.5.1. Função Index
- 2.5.2. Função IndexAny
- 2.5.3. Função IndexByte
- 2.5.4. Função IndexRune
- 2.6. IndexFunc e as funções unicode.Is…
- 2.7. Funções Join e Fields
- 2.7.1. Função Join
- 2.7.2. Função Fields
- 2.8. Funções LastIndex, LastIndexAny, LastIndexByte e LastIndexFunc
- 2.8.1. Função LastIndex
- 2.8.2. Função LastIndexFunc
- 2.9. Função Repeat
- 2.10. Função Replace e ReplaceAll
- 2.10.1. Assinatura das Funções
- 2.10.2. Função Replace
- 2.10.3. Função ReplaceAll
- 2.10.4. Exemplo de Uso
- 2.11. Funções Split, SplitN, SplitAfter e SplitAfterN
- 2.11.1. Assinatura das Funções
- 2.11.2. Funcionamento das Funções
- 2.11.3. Exemplo de Uso
- 2.12. Funções de Formatação Title e alguns To…
- 2.12.1. Funções Title, ToTitle, ToUpper e ToLower
- 2.12.2. Exemplo de Uso
- 2.13. Funções Trim…
- 2.13.1. Assinatura das Funções Trim…
- 2.13.2. Exemplo de Uso
- 3. Considerações Finais
No universo da programação, a escolha de uma linguagem de programação é frequentemente influenciada pela riqueza de sua biblioteca padrão. Por exemplo, o Python é renomado pelo lema “batteries included”, que evidencia sua vasta biblioteca padrão, capacitando os desenvolvedores a construir uma ampla gama de produtos de maneira eficiente. Uma expectativa semelhante recai sobre qualquer linguagem moderna, especialmente considerando a diversidade e a maturidade das linguagens já estabelecidas no mercado. Desde o seu surgimento, os criadores de Go (ou Golang) têm se dedicado a fornecer um ecossistema robusto para o desenvolvimento de aplicativos, equipado com ferramentas contemporâneas e essenciais para qualquer tipo de projeto.
A lista completa de pacotes inclusos em Go está disponível na página pkg.go.dev/std e também em alguns repositórios alternativos com formatação aprimorada, como o Devdocs.io/go. Neste artigo, fornecerei uma visão geral de alguns pacotes da biblioteca padrão que julgo serem particularmente significativos e aqueles que prevejo utilizar extensivamente no futuro. Além disso, pretendo incluir informações adicionais sobre outros pacotes imprescindíveis da biblioteca padrão em futuras edições.
Pacote fmt
O pacote fmt
provê uma série de funcionalidades para formatação de valores de entrada e saída em Go, com suas funções assemelhando-se às conhecidas printf
e scanf
da linguagem C.
Códigos de Formatação
A tabela a seguir apresenta os principais códigos de formatação utilizados com o pacote fmt
:
Código | Descrição |
---|---|
%% | caractere porcentagem (%) |
%v | formatação padrão para o tipo passado |
%T | imprime o tipo passado do valor passado |
%s | string |
%f | decimal de ponto flutuante |
%e ou %E | notação científica |
%q | string entre duplas aspas |
%c | o caractere representado pelo Unicode |
%d | inteiro decimal (base 10) |
%o e %O | base 8 e base 8 com prefixo “0o” |
%x e %X | base 16 e base 16 com a-f capitalizado |
%t | booleano (true/false) |
Para ilustrar a aplicação desses códigos, o código Go a seguir implementa alguns deles:
package main import "fmt" func main() { var ( a int64 = 2 b uint16 = 8 c float64 = 2.43342325 d bool = true e byte = 'a' f string = "albert" ) fmt.Printf("a: %v %T\n", a, a) fmt.Printf("b: %v %T\n", b, b) fmt.Printf("c: %v %T\n", c, c) fmt.Printf("d: %v %T\n", d, d) fmt.Printf("e: %v %T\n", e, e) fmt.Printf("f: %v %T\n", f, f) fmt.Println() fmt.Printf("%%d format in a: %03d**%+3d\n", a, a) fmt.Printf("%%d format in e: %02d %+2d\n", e, e) fmt.Printf("%%f format in c: %1.1f %.2f\n", c, c) fmt.Printf("%%q format in e and f:%q %q\n", e, f) fmt.Printf("%%o and %%O format in d:%o %O\n", b, b) fmt.Printf("%%s format in f: >|%s|< >|%8s|<\n", f, f) }
A saída do código é a seguinte:
rudson@suzail:format$ go run geral.go
a: 2 int64
b: 8 uint16
c: 2.43342325 float64
d: true bool
e: 97 uint8
f: albert string%d format in a: 002** +2
%d format in e: 97 +97
%f format in c: 2.4 2.43
%q format in e and f:’a’ “albert”
%o and %O format in d:10 0o10
%s format in f: >|albert|< >| albert|<
Como demonstrado, é possível especificar a largura do campo de saída adicionando um número após o símbolo “%
“, tanto para números quanto para strings.
Com números, é possível exibir o sinal (positivo ou negativo) usando o sinal “+
” logo após o “%
“, como em %+3d
. Para strings, o sinal “+
” força que a saída para %q
(ou %+q
) represente apenas caracteres ASCII.
Para números de ponto flutuante, você pode limitar o número de casas decimais após o ponto com a notação %.nf
, onde n
é o número de dígitos desejados após o ponto decimal.
Essas formatações são similares às da linguagem C e são usadas com funções do pacote fmt
que terminam com “f
“, como Printf
, scanf
, Errorf
, Fprintf
e Sscanf
.
Existem outras nuances nos códigos de formatação que não foram abordadas aqui, mas as apresentadas são essenciais para a maioria dos usos. Para um entendimento mais aprofundado, recomenda-se a consulta à documentação oficial.
Funções Print, Printf e Println
As funções Print
, Printf
e Println
do pacote fmt
constituem os métodos padrão de impressão na tela em Go. A função Print
executa a impressão na formatação padrão do tipo empregado. Já a função Println
é similar, mas adiciona uma quebra de linha ao final da impressão.
Exemplo de Uso:
package main import "fmt" func main() { nome, sobrenome := "Alberto", "Santos" idade := 35 fmt.Print(nome, " ", sobrenome) fmt.Println(" possui", idade, "anos.") fmt.Println("Fim") }
A saída deste código será:
rudson@suzail:format$ go run prints.go
Alberto Santos possui 35 anos.
Fim
Para uma formatação mais controlada, você pode usar Printf
, que permite especificar a formatação desejada. Por exemplo, as linhas 9, 10 e 11 do código anterior poderiam ser substituídas por:
... fmt.Printf("%s %s possui %d anos.\nFim\n", nome, sobrenome, idade) }
Retorno das Funções Print
A assinatura de uma função, que inclui sua linha de declaração, é instrutiva para entender as entradas e saídas esperadas. Por isso, as assinaturas das funções Print
, Printf
e Println
são apresentadas no início desta seção. Note que o tipo any
é usado nas assinaturas para indicar que essas funções aceitam uma sequência de argumentos de tipos variados. any
é um alias para interface{}
, o que significa que pode aceitar qualquer tipo.
func Print(a ...any) (n int, err error)
func Println(a ...any) (n int, err error)
func Printf(format string, a ...any) (n int, err error)
As entradas dessas funções são variádicas, indicadas por a ...any
, permitindo uma sequência de argumentos de tipos variados. Apenas Printf
difere um pouco, iniciando com uma string de formatação. O retorno dessas funções inclui um inteiro n
, que representa o número de bytes impressos, e um código de erro err
, caso ocorra algum problema durante a impressão.
Em Go, é possível ignorar completamente o retorno de uma função ou parte dele. Por exemplo, você pode ignorar o número de bytes impressos e capturar apenas o erro:
... _, err := fmt.Printf("%20s -> %2d", a, j)
No comando acima, o número de bytes impressos é ignorado e o erro, se houver, é armazenado na variável err
. Se err == nil
, a impressão foi bem-sucedida; caso contrário, err
conterá o código do erro gerado.
Embora seja possível rastrear erros nas funções de impressão, é comum invocá-las sem capturar os retornos, especialmente em contextos onde a precisão da saída não é crítica.
Funções Scan, Scanf e Scanln
As funções Scan
, Scanf
e Scanln
do pacote fmt
são usadas para ler a entrada do usuário a partir do teclado, de maneira similar às funções de impressão.
Separadores Espaço e Quebra de Linha
A função Scan
trata tanto os espaços quanto as quebras de linha como separadores. Por exemplo, a seguinte chamada de função:
... fmt.Scan(&a, &b, &c, &d)
com a
, b
, c
e d
sendo variáveis do tipo inteiro, aceitará tanto a entrada “1 2 3 4
” (quatro números separados por espaços na mesma linha), quanto qualquer combinação de quatro números, cada um seguido por um espaço ou uma quebra de linha.
Em contraste, a função Scanln
interrompe a leitura na primeira quebra de linha encontrada. Por exemplo, com a entrada:
1 2
3
4
Scan
funcionaria corretamente, mas Scanln
atribuiria 1
e 2
às variáveis a
e b
respectivamente, e deixaria c
e d
com valores zero, pois a leitura é interrompida na quebra de linha após “1 2
“.
A função Scanf
, por outro lado, lê a entrada de acordo com um formato específico. As quebras de linha precisam ser explicitamente incluídas na string de formatação. Por exemplo, o código:
... fmt.Scanf("%d %d\n%d\n%d", &a, &b, &c, &d)
lerá a entrada específica mostrada anteriormente, mas falhará com qualquer outra entrada diferente. A quantidade de espaços entre os números não é significativa para Scanf
.
Para entender melhor como essas funções lidam com a entrada, experimente diferentes entradas no código a seguir:
package main import "fmt" func main() { var a, b, c, d int64 fmt.Println("Entre com quatro valores: ") fmt.Scan(&a, &b, &c, &d) fmt.Printf("a:%d b:%d c:%d d:%d\n", a, b, c, d) fmt.Println("\nEntre com três valores na forma %%d %%d<ENTER> %%d %%d<ENTER>: ") fmt.Scanf("%d %d\n %d %d\n", &a, &b, &c, &d) fmt.Printf("a:%d b:%d c:%d d:%d\n", a, b, c, d) fmt.Println("\nEntre com quatro valores na forma com um \\n: ") fmt.Scanln(&a, &b, &c, &d) fmt.Printf("a:%d b:%d c:%d d:%d\n", a, b, c, d) }
Retorno das Funções Scan
Diferentemente das funções de impressão, os retornos das funções Scan
são cruciais para verificar se a entrada foi lida com sucesso. As assinaturas das funções Scan
, Scanln
e Scanf
são:
func Scan(a ...any) (n int, err error)
func Scanln(a ...any) (n int, err error)
func Scanf(format string, a ...any) (n int, err error)
O valor retornado n
indica o número de itens lidos com sucesso, e err
é o código de erro, se houver. O código a seguir mostra como verificar os retornos dessas funções para garantir que a entrada correta seja capturada:
package main import "fmt" func main() { var a, b, c, m int for { fmt.Println("\nEnter com os valores de a b c<ENTER>") n, err := fmt.Scanln(&a, &b, &c) if err == nil { m = n break } fmt.Printf("Entrou %d e esperado 3 entradas. Erro:%v\n", n, err) } fmt.Printf("Entrou com %d números, de valores: a = %d, b = %d e c = %d\n", m, a, b, c) }
Funções Sprint, Sprintln e Sprintf
As funções Sprint
, Sprintln
e Sprintf
são utilizadas para construir strings com base nos argumentos fornecidos. Elas são particularmente úteis para formatar strings e construir mensagens. Suas assinaturas são:
func Sprint(a …any) string
func Sprintln(a …any) string
func Sprintf(format string, a …any) string
Essas funções são amplamente usadas para montar strings. Sprintf
, em particular, é muito versátil, permitindo formatar a string de saída de maneira detalhada. Um uso comum de Sprintf
é definir a representação em string de tipos personalizados, como demonstrado no exemplo a seguir:
package main import "fmt" type pessoa struct { nome string sobreNome string idade int } func (p pessoa) String() string { return fmt.Sprintf("O %s %s possui %d anos.", p.nome, p.sobreNome, p.idade) } func main() { a := pessoa{ nome: "Alonso", sobreNome: "Bortolini", idade: 36, } fmt.Print(a) }
Neste exemplo, a função padrão de impressão para o tipo pessoa é sobrescrita, usando fmt.Sprintf
para formatar a string resultante. A execução deste código resulta em uma saída mais legível e personalizada para o tipo pessoa:
O Alonso Bortolini possui 36 anos.
Em suma, Sprint
e Sprintln
retornam uma string com a representação padrão dos tipos passados como argumentos, enquanto Sprintln
adiciona uma quebra de linha ao final. Por outro lado, Sprintf
permite construir uma string formatada, aproveitando os códigos de formatação que foram apresentados anteriormente.
Função Errorf
A função Errorf
é usada para criar mensagens de erro personalizadas e formatadas. Sua assinatura é:
func Errorf(format string, a ...any) error
Errorf
é extremamente útil para gerar mensagens de erro específicas, tornando a depuração e o tratamento de erros mais claros. O seguinte exemplo ilustra seu uso:
package main import ( "fmt" "log" ) type user struct { name string id int } func main() { u := user{"alves", 1001} err := fmt.Errorf("Usuário %s (id %d) não encontrado", u.name, u.id) log.Fatal(err) }
É importante observar que, seguindo as convenções do Go, as mensagens de erro devem começar com letra minúscula e não devem terminar com pontuação. A execução deste código gerará a seguinte saída:
rudson@suzail:~$ go run fmt_errorf
2022/05/16 10:16:28 Usuário alves (id 1001) não encontrado
exit status 1
rudson@suzail:~$ echo $?
1
O último comando no terminal, echo $?
, exibe o código de saída do programa. Um código de saída 0
indica que o programa foi executado com sucesso, enquanto um código diferente de zero sugere a ocorrência de algum erro. Neste caso, o código 1
indica que houve um erro no programa.
Como ler Strings com espaços no fmt?
Embora o pacote fmt
seja versátil e forneça várias funções para leitura e escrita de dados, ele não oferece uma maneira direta de ler strings com espaços a partir do teclado. Isso pode ser uma limitação quando se trata de ler entradas como nomes completos ou endereços, que naturalmente contêm espaços.
Para contornar essa limitação, você pode utilizar uma combinação do pacote bufio
com o pacote os
para ler diretamente do buffer de entrada. O exemplo a seguir demonstra como fazer isso:
package main import ( "bufio" "fmt" "os" ) func main() { fmt.Println("Nome completo:") scanner := bufio.NewReader(os.Stdin) line, _ := scanner.ReadString('\n') fmt.Printf("%q %T\n", line, line) }
Este código lê a entrada do teclado até que a tecla Enter (\n
) seja pressionada. A função scanner.ReadString('\n')
garante que a leitura continue até que uma quebra de linha seja encontrada. A saída para a entrada “Alberto Santos Dumont” seria:
rudson@suzail:~$ go run exemplo.go
Seu nome completo:
Alberto Santos Dumont
“Alberto Santos Dumont\n” string
Note que o caractere de quebra de linha (\n
) também é capturado. Uma discussão mais aprofundada sobre o pacote bufio
será realizada em futuros artigos.
Pacote Strings
O pacote strings
provê uma ampla gama de funções para manipulação de strings em Go. Devido à sua extensa lista de funcionalidades, vou apresentar as principais funções em ordem alfabética, conforme documentado oficialmente.
Função strings.Compare
func Compare(a, b string) int
A função Compare
retorna 0
se as strings a
e b
forem iguais, -1
se a
for menor que b
e +1
se a
for maior que b
. A comparação é feita lexicograficamente, ou seja, byte a byte. Os exemplos a seguir demonstram o comportamento desta função:
... fmt.Println(strings.Compare("a", "b")) // -1 fmt.Println(strings.Compare("a", "a")) // 0 fmt.Println(strings.Compare("b", "ab")) // 1
Funções Contains, ContainsAny e ContainsRune
O pacote strings
oferece várias funções para verificar a presença de sub-strings ou caracteres em uma string.
Função Contains
func Contains(s, ss string) bool
A função Contains
verifica se a sub-string ss
está contida na string s
, retornando true
se estiver presente. Por exemplo:
... fmt.Println(strings.Contains("seafood", "foo")) // true fmt.Println(strings.Contains("seafood", "bar")) // false fmt.Println(strings.Contains("seafood", "")) // true
Uma string vazia é considerada como estando contida em qualquer string, portanto, a função retorna true
nesse caso.
Função ContainsAny
func ContainsAny(s, chars string) bool
A função ContainsAny
verifica se pelo menos um dos caracteres da string chars
está presente na string s
. Por exemplo:
... fmt.Println(strings.ContainsAny("failure", "aj")) // true
Função ContainsRune
func ContainsRune(s string, r rune) bool
A função ContainsRune
verifica se o código rune
fornecido está presente na string s
. Por exemplo:
... fmt.Println(strings.ContainsRune("aardvark", 97)) // true
Neste caso, 97
é o código Unicode para o caractere “a
“, que está presente na string “aardvark
“.
Função Count
func Count(s, ss string) int
A função Count
retorna o número de ocorrências da sub-string ss
na string s
. Por exemplo:
... fmt.Println(strings.Count("aardvark", "aa")) // 1 fmt.Println(strings.Count("aardvark", "a")) // 3
A função contabiliza quantas vezes a sub-string aparece na string principal.
Função Cut
func Cut(s, sep string) (before, after string, found bool)
A função Cut
divide a string s
usando o separador sep
. Retorna as partes before
e after
separadas por sep
, e found
indica se o separador foi encontrado na string s
. Por exemplo:
... b, a, f := strings.Cut("Albert Eintein", "ert") fmt.Printf("before: %q\n after: %q\n found: %t \n\n", b, a, f) b, a, f = strings.Cut("Albert Eintein", "e") fmt.Printf("before: %q\n after: %q\n found: %t \n\n", b, a, f) b, a, f = strings.Cut("Albert Eintein", "see") fmt.Printf("before: %q\n after: %q\n found: %t \n\n", b, a, f)
Os exemplos demonstram como a função Cut
pode ser usada para separar uma string em duas partes com base em um separador especificado. O retorno deste código será:
before: "Alb"
after: " Eintein"
found: true
before: "Alb"
after: "rt Eintein"
found: true
before: "Albert Eintein"
after: ""
found: false
Funções Index, IndexAny, IndexByte e IndexRune
O pacote strings
fornece várias funções para localizar sub-strings ou caracteres dentro de uma string principal.
Função Index
func Index(s, ss string) int
Index
retorna o índice da primeira ocorrência da sub-string ss
dentro da string s
. Se ss
não for encontrada, a função retorna -1
. Por exemplo:
... fmt.Println(strings.Index("chicken", "ken")) // 4
Função IndexAny
func IndexAny(s, chars string) int
IndexAny
retorna o índice do primeiro caractere da string s
que está presente na string chars
. Se nenhum caractere for encontrado, retorna -1
. Por exemplo:
... fmt.Println(strings.IndexAny("chicken", "aeiouy")) // 2
Função IndexByte
func IndexByte(s string, c byte) int
IndexByte
retorna o índice da primeira ocorrência do byte c
na string s
. Se c
não for encontrado, retorna -1
. Por exemplo:
... fmt.Println(strings.IndexByte("gophers", 'h')) // 3
Função IndexRune
func IndexRune(s string, r rune) int
IndexRune
funciona de forma semelhante a IndexByte
, mas busca um rune
em vez de um byte. Por exemplo:
... fmt.Println(strings.IndexRune("chicken", 'k')) // 4
IndexFunc e as funções unicode.Is…
IndexFunc
retorna o índice do primeiro caractere em s
que satisfaça a função f
. Se nenhum caractere satisfizer f
, retorna -1
. f
aceita um rune
e retorna um bool
.
func IndexFunc(s string, f func(rune) bool) int
Um conjunto útil de funções que podem ser usadas com IndexFunc
são as funções Is...
do pacote unicode
, que determinam se um rune
satisfaz certas propriedades. Por exemplo, unicode.IsLetter(r rune) bool
retorna true
se r
for uma letra.
Função | Assinatura | True se rune é? |
---|---|---|
IsControl | func IsControl(r rune) bool | caractere de controle |
IsDigit | func IsDigit(r rune) bool | decimal |
IsGraphic | func IsGraphic(r rune) bool | caractere gráfico |
IsLetter | func IsLetter(r rune) bool | letra |
IsLower | func IsLower(r rune) bool | caractere minúsculo |
IsNumber | func IsNumber(r rune) bool | número |
IsPunct | func IsPunct(r rune) bool | caractere de pontuação |
IsSpace | func IsSpace(r rune) bool | espaço |
IsPrint | func IsPrint(r rune) bool | imprimível (caracteres, letras, …) |
IsSymbol | func IsSymbol(r rune) bool | símbolo |
IsUpper | func IsUpper(r rune) bool | caractere maiúsculo |
Um exemplo de uso de IndexFunc
com funções unicode.Is...
:
package main import ( "fmt" "strings" "unicode" ) func main() { str := "A Revolução Americana, ou Revolução Americana de 1776, teve suas raízes" fmt.Println(strings.IndexFunc(str, unicode.IsNumber)) fmt.Println(strings.IndexFunc(str, unicode.IsPunct)) fmt.Println(strings.IndexFunc(str, unicode.IsLetter)) fmt.Println(strings.IndexFunc(str, unicode.IsSpace)) fmt.Println(strings.IndexFunc(str, unicode.IsUpper)) }
Funções Join e Fields
Função Join
func Join(elems []string, sep string) string
Join
une os elementos de elems
em uma única string, separados por sep
. Por exemplo, se você tiver uma slice de strings ["Alberto", "Santos", "Dumont"]
e quiser uni-las em uma string única separada por underscores, você usaria Join
.
Função Fields
func Fields(s string) []string
Fields
divide a string s
em uma slice de strings, separando por espaços. É o inverso da função Join
quando o separador é um espaço.
Um exemplo de uso de Join
e Fields
:
package main import ( "fmt" "strings" ) func main() { nome := "Alberto Santos Dumont" split := strings.Fields(nome) fmt.Println(split) join := strings.Join(split, "_") fmt.Println(join) }
Funções LastIndex, LastIndexAny, LastIndexByte e LastIndexFunc
O pacote strings
também oferece funções que operam de maneira semelhante às funções Index...
, mas procuram a última ocorrência de uma sub-string ou caractere em uma string principal.
Função LastIndex
func LastIndex(s, ss string) int
LastIndex
retorna o índice da última ocorrência da sub-string ss
dentro da string s
. Se ss
não for encontrada, a função retorna -1
. Por exemplo:
... str := "Pop!_OS is an operating system..." fmt.Println(strings.LastIndex(str, "op")) // Retorna o índice da última ocorrência de "op"
Função LastIndexFunc
func LastIndexFunc(s string, f func(rune) bool) int
LastIndexFunc
retorna o índice do último caractere em s
que satisfaz a função f
. Se nenhum caractere satisfizer f
, retorna -1
. f
aceita um rune
e retorna um bool
.
Um exemplo de uso de LastIndexFunc
com funções unicode.Is...
:
package main import ( "fmt" "strings" "unicode" ) func printArrow(r int) { fmt.Printf("%s>\n", strings.Repeat("-", r-1)) } func main() { str := "The American Revolution, or American Revolution of 1776, had its roots" fmt.Println(str) printArrow(strings.LastIndexFunc(str, unicode.IsNumber)) // Índice do último número printArrow(strings.LastIndexFunc(str, unicode.IsPunct)) // Índice do último caractere de pontuação printArrow(strings.LastIndexFunc(str, unicode.IsLetter)) // Índice da última letra printArrow(strings.LastIndexFunc(str, unicode.IsSpace)) // Índice do último espaço printArrow(strings.LastIndexFunc(str, unicode.IsUpper)) // Índice da última letra maiúscula }
Os índices retornados são usados pela função printArrow para desenhar uma seta até a posição do caractere encontrado. Veja o resultado abaixo:
The American Revolution, or American Revolution of 1776, had its roots
----------------------------------------------------->
------------------------------------------------------>
-------------------------------------------------------------------->
--------------------------------------------------------------->
------------------------------------>
Função Repeat
A função Repeat
é utilizada para criar uma nova string consistindo de múltiplas cópias de uma string original.
Assinatura da Função
func Repeat(s string, count int) string
Repeat recebe uma string s
e um número inteiro count
, retornando uma nova string que consiste na string s
repetida count
vezes. Se count
for negativo ou zero, a função retorna uma string vazia.
... fmt.Print(strings.Repeat("ha ", 3)) // imprime "ha ha ha "
Função Replace e ReplaceAll
As funções Replace
e ReplaceAll
são utilizadas para substituir ocorrências de uma sub-string dentro de uma string principal.
Assinatura das Funções
func Replace(s, old, new string, n int) string
func ReplaceAll(s, old, new string) string
Função Replace
Replace
retorna uma nova string baseada na string s
, substituindo as primeiras n
ocorrências da string old
pela string new
. Se n
for -1
, todas as ocorrências serão substituídas.
Função ReplaceAll
ReplaceAll
é uma variação da função Replace
onde todas as ocorrências da string old
são substituídas pela string new
, independentemente do número de ocorrências.
Exemplo de Uso
O exemplo a seguir demonstra como usar as funções Replace
e ReplaceAll
para substituir sub-strings em uma string principal:
package main import ( "fmt" "strings" ) func main() { str := "A Revolução Americana, ou Revolução Americana de 1776, teve suas raízes" fmt.Println(strings.Replace(str, "Americana", "___________", 2)) fmt.Println(strings.Replace(str, "Americana", "___________", -1)) fmt.Println(strings.ReplaceAll(str, "Americana", "___________")) }
As três chamadas às funções Replace
e ReplaceAll
, linhas 11 a 13, produzirão o mesmo resultado, substituindo todas as ocorrências de “Americana” por “_“:
A Revolução ___________, ou Revolução ___________ de 1776, teve suas raízes
A Revolução ___________, ou Revolução ___________ de 1776, teve suas raízes
A Revolução ___________, ou Revolução ___________ de 1776, teve suas raízes
Funções Split, SplitN, SplitAfter e SplitAfterN
O pacote strings
oferece funções para dividir uma string em uma slice de strings com base em um separador especificado.
Assinatura das Funções
func Split(s, sep string) []string
func SplitN(s, sep string, n int) []string
func SplitAfter(s, sep string) []string
func SplitAfterN(s, sep string, n int) []string
Funcionamento das Funções
Split
: Divide a strings
em todos os pontos onde o separadorsep
ocorre.SplitN
: Semelhante aSplit
, mas divide a strings
em no máximon
substrings.SplitAfter
: Divide a strings
em todos os pontos logo após o separadorsep
, mantendo o separador como parte da substring precedente.SplitAfterN
: Semelhante aSplitAfter
, mas divide a strings
em no máximon
substrings.
Exemplo de Uso
O exemplo a seguir demonstra como usar as funções Split
, SplitN
, SplitAfter
e SplitAfterN
para dividir uma string:
package main import ( "fmt" "strings" ) func main() { str := "a,b,c,d" // Divide a string em todas as ocorrências do separador fmt.Printf(" Split: %q\n", strings.Split(str, ",")) // Divide a string em no máximo n substrings fmt.Printf(" SplitN: %q\n", strings.SplitN(str, ",", 2)) // Divide a string em todas as ocorrências do separador, mantendo o separador com a substring anterior fmt.Printf(" SplitAfter: %q\n", strings.SplitAfter(str, ",")) // Divide a string em no máximo n substrings, mantendo o separador com a substring anterior fmt.Printf("SplitAfterN: %q\n", strings.SplitAfterN(str, ",", 2)) }
O retorno deste código será:
Split: ["a" "b" "c" "d"]
SplitN: ["a" "b,c,d"]
SplitAfter: ["a," "b," "c," "d"]
SplitAfterN: ["a," "b,c,d"]
Note que as funções SplitAfter
e SplitAfterN
mantêm o separador, neste caso a vírgula, e o fatiamento é feito logo após o separador, como indicado pelo after
no nome da função.
Funções de Formatação Title e alguns To…
O pacote strings
fornece funções para alterar a formatação de strings em termos de caixa alta e baixa.
Funções Title, ToTitle, ToUpper e ToLower
func Title(s string) string
func ToTitle(s string) string
func ToUpper(s string) string
func ToLower(s string) string
Title
converte a primeira letra de cada palavra em maiúscula.ToTitle
converte todas as letras em maiúsculas, semelhante aToUpper
.ToUpper
converte todas as letras da string em maiúsculas.ToLower
converte todas as letras da string em minúsculas.
Exemplo de Uso
O exemplo a seguir demonstra como usar as funções Title
, ToTitle
, ToUpper
, e ToLower
:
package main import ( "fmt" "strings" ) func main() { str := "prIncíPios básICos do paSTafArismo" fmt.Println(strings.Title(str)) fmt.Println(strings.ToTitle(str)) fmt.Println(strings.ToUpper(str)) fmt.Println(strings.ToLower(str)) fmt.Println(strings.Title(strings.ToLower(str))) }
O código acima produzirá a saída:
PrIncíPios BásICos Do PaSTafArismo
PRINCÍPIOS BÁSICOS DO PASTAFARISMO
PRINCÍPIOS BÁSICOS DO PASTAFARISMO
princípios básicos do pastafarismo
Princípios Básicos Do Pastafarismo
Funções Trim…
O pacote strings
oferece diversas funções Trim...
para remover caracteres específicos do início e/ou do final de uma string.
Assinatura das Funções Trim…
func Trim(s, cutset string) string
func TrimFunc(s string, f func(rune) bool) string
func TrimLeft(s, cutset string) string
func TrimLeftFunc(s string, f func(rune) bool) string
func TrimPrefix(s, prefix string) string
func TrimRight(s, cutset string) string
func TrimRightFunc(s string, f func(rune) bool) string
func TrimSpace(s string) string
func TrimSuffix(s, suffix string) string
Trim
remove caracteres especificados porcutset
do início e do final des
.TrimFunc
usa uma função de filtro para determinar quais caracteres remover.TrimLeft
eTrimRight
removem caracteres do início ou do final des
, respectivamente.TrimPrefix
eTrimSuffix
removem um prefixo ou um sufixo específico des
.TrimSpace
remove espaços em branco do início e do final des
.
Exemplo de Uso
O exemplo a seguir ilustra o uso de várias funções Trim...
:
package main import ( "fmt" "strings" "unicode" ) func removeSelection(r rune) bool { if unicode.IsNumber(r) || r == ' ' || r == 'o' { return true } return false } func main() { var ( str1 = "---Mais sem graça que a top-model ..." str2 = " Mas ontem eu recebi um telegrama " str3 = "o Prêmio Nobel de Física de 1921" ) fmt.Printf("%q\n", strings.Trim(str1, "- .")) fmt.Printf("%q\n", strings.TrimLeft(str1, "- .")) fmt.Printf("%q\n", strings.TrimRight(str1, "- .")) fmt.Printf("%q\n", strings.TrimPrefix(str1, "-")) fmt.Printf("%q\n", strings.TrimSuffix(str1, ".")) fmt.Printf("%q\n", strings.TrimSpace(str2)) fmt.Printf("%q\n", strings.TrimRightFunc(str3, unicode.IsNumber)) fmt.Printf("%q\n", strings.TrimFunc(str3, removeSelection)) }
O código acima produzirá a saída:
"Mais sem graça que a top-model"
"Mais sem graça que a top-model ..."
"---Mais sem graça que a top-model"
"--Mais sem graça que a top-model ..."
"---Mais sem graça que a top-model .."
"Mas ontem eu recebi um telegrama"
"o Prêmio Nobel de Física de "
"Prêmio Nobel de Física de"
Considerações Finais
Ao longo deste artigo, exploramos uma variedade de funções fundamentais dos pacotes fmt
e strings
do GoLang, mergulhando nas nuances e capacidades que cada função oferece. A jornada pelas diversas funcionalidades, desde formatação de strings e operações de entrada/saída até manipulações complexas de texto, demonstrou a versatilidade e o poder que essas bibliotecas padrão colocam à disposição dos desenvolvedores.
A discussão detalhada sobre cada função não foi apenas uma revisão, mas também uma oportunidade de reconhecer a evolução constante do GoLang e as práticas recomendadas para seu uso eficaz. A familiaridade com essas funções é vital, pois elas constituem a base sobre a qual operações mais complexas são construídas e soluções inovadoras são desenvolvidas.
No próximo artigo, planejo expandir nosso horizonte, explorando outros pacotes cruciais da biblioteca padrão do GoLang. O objetivo é aprofundar ainda mais nosso conhecimento e compreensão do ecossistema GoLang, abordando pacotes que são essenciais para o desenvolvimento robusto e eficiente de aplicações.