Fundamentos de Strings em Go

GolangBeginner
Pratique Agora

Introdução

Na lição anterior, aprendemos que os caracteres em Go são codificados usando UTF-8 e armazenados como os tipos byte ou rune. Agora, vamos discutir strings, que são coleções de caracteres. Vamos explorar este tópico juntos.

Pontos de Conhecimento:

  • O que é uma string
  • Criando uma string
  • Declarando uma string
  • Funções de string comuns
  • Acessando elementos de string
Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 100%. Recebeu uma taxa de avaliações positivas de 91% dos estudantes.

O que é uma String

No primeiro programa que aprendemos em Go, imprimimos a string "hello, world".

Uma string é um tipo de dado básico em Go, também conhecido como literal de string. Ela pode ser entendida como uma coleção de caracteres e ocupa um bloco contínuo de memória. Este bloco de memória pode armazenar qualquer tipo de dado, como letras, texto, emoji, e assim por diante.

No entanto, ao contrário de outras linguagens, as strings em Go são imutáveis e não podem ser modificadas. Isso significa que, uma vez que uma string é criada, você não pode alterar seus caracteres individuais. Se você precisar de uma versão modificada de uma string, você terá que criar uma nova.

Criando uma String

Strings podem ser declaradas de várias maneiras. Vamos dar uma olhada no primeiro método. Crie um novo arquivo chamado string.go:

touch ~/project/string.go

Escreva o seguinte código:

package main

import "fmt"

func main() {
    // Use a palavra-chave var para criar uma variável string a
    var a string = "labex"
    a = "labex" // Atribui "labex" à variável a

    // Declara a variável b e atribui seu valor
    var b string = "labs"

    // A declaração de tipo pode ser omitida
    var c = "Monday"

    // Use := para declaração e atribuição rápidas
    d := "Sunday"
    fmt.Println(a, b, c, d)
}

O código acima demonstra como criar strings usando a palavra-chave var e o operador :=. Se você atribuir um valor ao criar uma variável com var, você pode omitir a declaração de tipo, como mostrado na criação da variável c. O operador := é uma forma abreviada para declarar e inicializar uma variável em Go. Ele infere automaticamente o tipo da variável a partir do valor atribuído a ela. Usá-lo tornará seu código mais conciso.

go run string.go

A saída esperada é a seguinte:

labex labs Monday Sunday

Declarando uma String

Na maioria dos casos, usamos aspas duplas "" para declarar strings. A vantagem das aspas duplas é que elas podem ser usadas como sequências de escape. Por exemplo, no programa abaixo, usamos a sequência de escape \n para criar uma nova linha:

package main

import "fmt"

func main() {
    x := "linux\nlabex"
    fmt.Println(x)
}
go run string.go

A saída esperada é a seguinte:

linux
labex

Aqui estão algumas sequências de escape comuns:

Símbolo Descrição
\n Nova linha
\r Retorno de carro
\t Tabulação
\b Retrocesso
\\ Barra invertida
\' Aspas simples
\" Aspas duplas

Se você deseja preservar o formato original do texto ou precisa usar várias linhas, você pode usar acentos graves (backticks) para representá-los:

package main

import "fmt"

func main() {
    // Output the ASCII art of "labex"
    ascii := `
        ##        #####   #########  ########## ##    #
        ##       ##  ##  ##    ## ##       ##  #
        ##      ##    ## #########  #########    ##
        ##      ########## ##    ## ##        ##
        ##      ##    ## ##    ## ##       ##  #
        ########## ##    ## #########  ########## ##    #`
    fmt.Println(ascii)
}

Acentos graves são comumente usados em prompts, templates HTML e outros casos onde você precisa preservar o formato original da saída. O texto dentro dos acentos graves é tratado como um literal de string bruto (raw string literal), o que significa que as sequências de escape não são interpretadas. Isso torna conveniente incluir texto de várias linhas e caracteres especiais sem ter que escapá-los.

Obtendo o Comprimento de uma String

Na lição anterior, aprendemos que os caracteres em inglês e os sinais de pontuação gerais ocupam um byte.

Portanto, em Go, podemos usar a função len() para obter o comprimento em bytes de uma string. Se não houver caracteres que ocupem vários bytes, a função len() pode ser usada para medir com precisão o comprimento da string.

Se uma string contiver caracteres que ocupam vários bytes, você pode usar a função utf8.RuneCountInString para obter o número real de caracteres na string.

Vamos ver um exemplo. Escreva o seguinte código no arquivo string.go:

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    // Declare two empty strings using var and :=
    var a string
    b := ""

    c := "labex"
    d := "abc"


    // Output byte length
    fmt.Printf("The value of a is %s, the byte length of a is: %d\n", a, len(a))
    fmt.Printf("The value of b is %s, the byte length of b is: %d\n", b, len(b))
    fmt.Printf("The value of c is %s, the byte length of c is: %d\n", c, len(c))
 fmt.Printf("The value of d is %s, the byte length of d is: %d\n", d, len(d))


    // Output string length
    fmt.Printf("The length of c is: %d\n", utf8.RuneCountInString(c))
 fmt.Printf("The length of d is: %d\n", utf8.RuneCountInString(d))
}
go run string.go

A saída esperada é a seguinte:

The value of a is , the byte length of a is: 0
The value of b is , the byte length of b is: 0
The value of c is labex, the byte length of c is: 5
The value of d is abc, the byte length of d is: 3
The length of c is: 5
The length of d is: 3

No programa, primeiro declaramos duas strings vazias e as strings labex e abc. Você pode ver que seus comprimentos em bytes e comprimentos reais são os mesmos, pois eles contêm apenas caracteres de um byte.

Acessando Elementos de String

Como strings são essencialmente sequências de bytes, podemos acessar bytes ou caracteres individuais em uma string usando seu índice. Em Go, a indexação de strings começa em 0, como arrays.

No entanto, é importante lembrar que acessar elementos de string usando o índice retorna um byte, não um caractere (rune). Se a string contiver caracteres de vários bytes, você precisa ter cuidado ao usar índices, pois pode não obter o caractere completo. Para obter caracteres individuais (rune) com segurança, você pode iterar pela string usando um loop for...range, que lida com a codificação UTF-8 corretamente.

Vamos adicionar o seguinte código ao arquivo string.go:

package main

import (
 "fmt"
 "unicode/utf8"
)

func main() {
 str := "Hello, world!"

 // Accessing byte by index
 fmt.Printf("Byte at index 0: %c\n", str[0]) // Output: H
 fmt.Printf("Byte at index 7: %c\n", str[7]) // Output: w

    // Iterate using for...range to safely get runes
    fmt.Println("Iterating through runes:")
    for index, char := range str {
        fmt.Printf("Index: %d, Char: %c\n", index, char)
    }

 // Getting the number of runes
 fmt.Printf("Number of runes (characters) in the string: %d\n", utf8.RuneCountInString(str))

}

Agora execute o programa:

go run string.go

A saída é:

Byte at index 0: H
Byte at index 7: w
Iterating through runes:
Index: 0, Char: H
Index: 1, Char: e
Index: 2, Char: l
Index: 3, Char: l
Index: 4, Char: o
Index: 5, Char: ,
Index: 6, Char:
Index: 7, Char: w
Index: 8, Char: o
Index: 9, Char: r
Index: 10, Char: l
Index: 11, Char: d
Index: 12, Char: !
Number of runes (characters) in the string: 13

Nesta saída, você pode ver que:

  1. Acessar uma string por um índice específico retorna um byte.
  2. Usar um loop for...range permite que você itere pelos runes corretamente.

Este exemplo destaca a diferença fundamental entre byte e rune e a importância de usar os métodos apropriados ao lidar com caracteres em strings Go.

Convertendo Strings e Inteiros

Podemos usar funções do pacote strconv para converter entre strings e inteiros:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // Declare a string a and an integer b
    a, b := "233", 223

    // Use Atoi to convert a string to an integer
    c, _ := strconv.Atoi(a)

    // Use Sprintf and Itoa functions respectively
    // to convert an integer to a string
    d1 := fmt.Sprintf("%d", b)
    d2 := strconv.Itoa(b)

    fmt.Printf("The type of a: %T\n", a)   // string
    fmt.Printf("The type of b: %T\n", b)   // int
    fmt.Printf("The type of c: %T\n", c)   // int
    fmt.Printf("The type of d1: %T\n", d1) // string
    fmt.Printf("The type of d2: %T\n", d2) // string
}
go run string.go

A saída esperada é a seguinte:

The type of a: string
The type of b: int
The type of c: int
The type of d1: string
The type of d2: string

No programa, usamos a função Sprintf() do pacote fmt, que tem o seguinte formato:

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

format é uma string com sequências de escape, a é uma constante ou variável que fornece valores para as sequências de escape, e ... significa que pode haver múltiplas variáveis do mesmo tipo que a. A string após a função representa que Sprintf retorna uma string. Aqui está um exemplo de como usar esta função:

a = fmt.Sprintf("%d+%d=%d", 1, 2, 3)
fmt.Println(a) // 1+2=3

Neste trecho de código, o format é passado com três variáveis inteiras 1, 2 e 3. O caractere de escape inteiro %d em format é substituído pelos valores inteiros, e a função Sprintf retorna o resultado após a substituição, 1+2=3.

Além disso, observe que ao usar strconv.Atoi() para converter uma string em um inteiro, a função retorna dois valores, o inteiro convertido val e o código de erro err. Como em Go, se você declara uma variável, você deve usá-la, podemos usar um sublinhado _ para ignorar a variável err.

Quando strconv.Atoi() converte corretamente, err retorna nil. Quando ocorre um erro durante a conversão, err retorna a mensagem de erro, e o valor de val será 0. Você pode alterar o valor da string a e substituir o sublinhado por uma variável normal para experimentar por si mesmo. Esta é uma boa prática para o tratamento de erros (error handling), que é uma parte crucial da programação em Go.

Concatenando Strings

A maneira mais simples de concatenar duas ou mais strings é usar o operador +. Também podemos usar a função fmt.Sprintf() para concatenar strings. Vamos dar uma olhada em um exemplo:

package main

import (
    "fmt"
)

func main() {
    a, b := "lab", "ex"
    // Concatenate using the simplest method, +
    c1 := a + b
    // Concatenate using the Sprintf function
    c2 := fmt.Sprintf("%s%s", a, b)
    fmt.Println(a, b, c1, c2) // lab ex labex labex
}
go run string.go

A saída esperada é a seguinte:

lab ex labex labex

No programa, também usamos a função Sprintf() do pacote fmt para concatenar strings e imprimir os resultados. Ambos os métodos são formas comuns de concatenar strings, e a escolha entre eles geralmente depende da legibilidade e da preferência pessoal.

Removendo Espaços em Branco no Início e no Fim de uma String

Podemos usar a função strings.TrimSpace para remover espaços em branco no início e no fim de uma string. A função recebe uma string como entrada e retorna a string com os espaços em branco do início e do fim removidos. O formato é o seguinte:

func TrimSpace(s string) string

Aqui está um exemplo:

package main

import (
    "fmt"
    "strings"
)

func main() {
    a := " \t \n  labex \n \t labs"
    fmt.Println(strings.TrimSpace(a))
}
go run string.go

A saída esperada é a seguinte:

labex
         labs

Observe que strings.TrimSpace() remove apenas os espaços em branco no início e no fim da string; os espaços em branco dentro da string permanecem como estão.

Resumo

Para resumir o que aprendemos nesta lição:

  • A relação entre strings e caracteres
  • Duas maneiras de declarar strings, usando aspas duplas e acentos graves (backticks).
  • Acessando elementos de uma string usando índice (acesso por byte) e for...range (acesso por rune).
  • Obtendo o comprimento de uma string usando len() (comprimento em bytes) e utf8.RuneCountInString (comprimento em caracteres/rune).
  • Convertendo strings e inteiros usando strconv.Atoi() e strconv.Itoa().
  • Concatenando strings usando o operador + e fmt.Sprintf().
  • Removendo espaços em branco no início e no fim de uma string usando strings.TrimSpace().

Nesta lição, explicamos as strings que usamos no dia a dia. Aprendemos sobre a relação entre strings e caracteres, dominamos a criação e declaração de strings e adquirimos algum conhecimento sobre funções de string comuns. Também aprendemos como acessar com segurança caracteres individuais em uma string, especialmente ao lidar com caracteres multi-byte, e agora entendemos alguns métodos cruciais de manipulação de strings. Isso lhe dá uma base sólida para trabalhar com dados de string em Go.