Introdução à Linguagem de Programação Go

Tipos de Dados Fundamentais em Go

Tipos Inteiros

A linguagem Go oferece tanto inteiros com sinal quanto sem sinal.

  • Inteiros com sinal: int, int8, int16, int32, int64
  • Inteiros sem sinal: uint, uint8, uint16, uint32, uint64, uintptr

Os tipos int e uint variam conforme a arquitetura do processador, representando o tamanho da palavra da máquina. O int é o tipo de inteiro com sinal mais amplamente utilizado.

Exemplo de declaração de uma variável inteira em Go:

var contador int;

Tipos de Ponto Flutuante

Go suporta dois tipos de ponto flutuante:

  • float32: com faixa aproximada de 1.4 × 10⁻⁴⁵ a 3.4 × 10³⁸
  • float64: com faixa aproximada de 4.9 × 10⁻³²⁴ a 1.8 × 10³⁰⁸

Exemplo de declaração:

var distancia float32;
var precisao float64;

Tipo Booleano

Uma variável booleana só pode assumir dois valores: true ou false. Expressões condicionais em if e for resultam em valores boooleanos.

Operadores como ==, >, <, && e || produzem resultados booleanos.

Declaração de uma variável booleana:

var ativo bool;

Caracteres

Em Go, caracteres são representados de duas formas:

  • Tipo byte (alias para uint8), que representa um caractere ASCII.
  • Tipo rune (alias para int32), que representa um caractere Unicode (UTF-8), adequado para textos com caracteres acentuados ou idiomas complexos.

Um caractere ASCII ocupa um byte. O padrão ASCII define 128 caracteres, de 0 a 127.

Declaração de caracteres usando aspas simples:

var simbolo byte = 'A' var codigo byte = 65 var hexa byte = '\x41' var octal byte = '\101'

<p>Para caracteres Unicode, utiliza-se <code>rune</code> e prefixos como <code>\u</code> ou <code>\U</code>:</p>
<code>var caractereUnicode rune = '\u0041' // Representa 'A'</code>
<p>Exemplo completo demonstrando caracteres e funções unicode:</p>
<code>package main

import (
    "fmt"
    "unicode"
)

func main() {
    var primeiro byte = 'A'
    fmt.Println("Valor numérico:", primeiro)
    var segundo byte = 65
    fmt.Println("Valor numérico:", segundo)
    var terceiro byte = '\x41'
    fmt.Println("Valor numérico:", terceiro)
    var quarto byte = '\101'
    fmt.Println("Valor numérico:", quarto)

    fmt.Printf("Caractere: %c\n", primeiro)
    fmt.Printf("Caractere: %c\n", segundo)
    fmt.Printf("Caractere: %c\n", terceiro)
    fmt.Printf("Caractere: %c\n", quarto)

    var numeral rune = '1'
    var codigoUnicode rune = 49

    fmt.Println(unicode.IsLetter('A'))
    fmt.Println(unicode.IsSpace(' '))
    fmt.Println(unicode.IsDigit(numeral))
    fmt.Println(unicode.IsDigit(codigoUnicode))
}</code>
<h3>Caracteres de Escape</h3>
<p>Em strings, caracteres de escape são usados para inserir elementos especiais:</p>
  • \n: nova linha
  • \r: retorno de carro
  • \t: tabulação
  • \u ou \U: caractere Unicode
  • \\: barra invertida literal

Cadeias de Caracteres (Strings)

Uma string é uma sequência imutável de bytes, tipicamente usada para armazenar texto legível. Go suporta nativamente a codificação UTF-8.

Exemplo de declaração:

var mensagem string = "Olá, mundo!"

Busca em Strings

Para localizar substrings, podem-se usar funções do pacote strings:

  • strings.Index(): busca da esquerda para a direita.
  • strings.LastIndex(): busca da direita para a esquerda.

Exemplo de busca:

package main

import (
    "fmt"
    "strings"
)

func main() {
    texto := "Olá, mundo! Bem-vindo ao Go!"

    pos1 := strings.Index(texto, "mundo!")
    pos2 := strings.LastIndex(texto, "Go!")
    fmt.Println("Primeira ocorrência de 'mundo!':", pos1)
    fmt.Println("Última ocorrência de 'Go!':", pos2)

    pos3 := strings.Index(texto, "ausente")
    fmt.Println("Resultado para substring ausente:", pos3)
}

Uso de Crases

Strings entre crases (```) são interpretadas literalmente, sem processar caracteres de escape.

Exemplo:

fmt.Println("Linha com tabulação:\tconteúdo")
fmt.Println(`Linha com tabulação:\tconteúdo literal`)

Iteração em Strings

Strings ASCII podem ser percorridas com for convencional ou for range, enquanto strings Unicode devem ser percorridas com for range.

Exemplo:

package main

import "fmt"

func main() {
    textoASCII := "Hello World"
    textoUnicode := "Olá, mundo!"

    for i := 0; i < len(textoASCII); i++ {
        fmt.Printf("%c ", textoASCII[i])
    }
    fmt.Println()

    for _, caractere := range textoASCII {
        fmt.Printf("%c ", caractere)
    }
    fmt.Println()

    for _, caractere := range textoUnicode {
        fmt.Printf("%c ", caractere)
    }
}

Conversão de Tipos

Go não permite conversões implícitas; todas as transformações devem ser explícitas. Use funções do pacote strconv para converter entre strings e outros tipos numéricos.

Funções comuns:

  • strconv.Atoi(string) para inteiro.
  • strconv.Itoa(int) para string.
  • strconv.ParseFloat(string, bits) para ponto flutuante.
  • strconv.FormatFloat(valor, formato, precisão, bits) para formatar float como string.

Exemplo de conversão:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    strNumero := "42"
    numero, _ := strconv.Atoi(strNumero)
    fmt.Printf("String '%s' convertido para inteiro: %d\n", strNumero, numero)

    inteiro := 100
    strResultado := strconv.Itoa(inteiro)
    fmt.Printf("Inteiro %d convertido para string: '%s'\n", inteiro, strResultado)

    strFloat := "3.14"
    float, _ := strconv.ParseFloat(strFloat, 64)
    fmt.Printf("String '%s' convertido para float64: %f\n", strFloat, float)

    valorFloat := 2.718
    strFormatado := strconv.FormatFloat(valorFloat, 'f', 2, 64)
    fmt.Printf("Float %f formatado como string: '%s'\n", valorFloat, strFormatado)
}

Constantes e Gerador iota

Constantes são declaradas com const e seus valores são determinados em tempo de compilação. Em declarações em bloco, omitir o valor em uma linha herda o valor e tipo da constante anterior.

const (
    PI    = 3.14159
    GRAVIDADE
    NOME  = "Go"
    VERSAO
)

O gerador iota simplifica a criação de constantes sequenciais, começando em 0 e incrementando automaticamente.

const (
    DOMINGO = iota // 0
    SEGUNDA        // 1
    TERCA          // 2
    QUARTA         // 3
    QUINTA         // 4
    SEXTA          // 5
    SABADO         // 6
)

Ponteiros

Ponteiros armazenam endereços de memória de variáveis, permitindo modificá-las diretamente.

Declarar um ponteiro:

var ptr *int

Obter o endereço de uma variável com &:

valor := 10
ptr = &valor

Acessar ou modificar o valor apontado com *:

fmt.Println(*ptr)  // Imprime 10
*ptr = 20          // Altera o valor para 20

Exemplo completo:

package main

import "fmt"

func main() {
    x := 10
    ptr := &x
    fmt.Println("Valor original:", *ptr)
    *ptr = 25
    fmt.Println("Valor modificado:", x)
}

Arrays e Slices

Arrays

Arrays são estruturas de tamanho fixo que armazenam elementos do mesmo tipo.

var notas [5]int
notas = [5]int{9, 8, 7, 6, 5}
ou
notas := [...]int{9, 8, 7, 6, 5}

Slices

Slices são referências a segmentos de arrays, com tamanho dinâmico. Eles armazenam um ponteiro para o array subjacente, comprimento e capacidade.

Criar um slice a partir de um array:

array := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := array[3:6] // Inclui índices 3, 4, 5

Declarar um slice vazio:

var numeros []int

Usar make para criar um slice com capacidade específica:

slice := make([]float64, 5, 10) // Comprimento 5, capacidade 10

Copiar slices com copy:

origem := []int{1, 2, 3, 4, 5}
destino := make([]int, 3)
copiados := copy(destino, origem) // Copia os 3 primeiros elementos

Estruturas e Métodos

Structs

Structs agrupam campos de diferentes tipos em um único tipo personalizado.

type Pessoa struct {
    Nome string
    Idade int
    Ativo bool
}

Instanciar uma struct:

p1 := Pessoa{Nome: "Ana", Idade: 30, Ativo: true}
ou
var p2 Pessoa
p2.Nome = "Bruno"

Structs anônimos podem ser usados para dados temporários:

temp := struct {
    Codigo int
    Descricoa string
}{1, "Item temporário"}

Métodos

Métodos são funções associadas a um tipo. O receptor pode ser por valor ou por ponteiro.

type Contador struct {
    valor int
}

// Receptor por valor: não modifica o original
func (c Contador) Incrementar() {
    c.valor++
}

// Receptor por ponteiro: modifica o original
func (c *Contador) Resetar() {
    c.valor = 0
}

Interfaces

Interfaces definem conjuntos de métodos que um tipo deve implementar. A implementação é implícita.

type Forma interface {
    Area() float64
    Perimetro() float64
}

type Retangulo struct {
    Largura, Altura float64
}

func (r Retangulo) Area() float64 {
    return r.Largura * r.Altura
}

func (r Retangulo) Perimetro() float64 {
    return 2 * (r.Largura + r.Altura)
}

Uma variável de interface pode armazenar qualquer tipo que implemente seus métodos.

var f Forma = Retangulo{Largura: 5, Altura: 10}
fmt.Println("Área:", f.Area())

Controle de Fluxo e Erros

Estruturas condicionais como if-else, switch, e loops for (incluindo for range) são fundamentais.

Go usa panic para erros graves e recover para recuperação dentro de funções defer.

func operacaoRisco() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Erro recuperado:", r)
        }
    }()
    panic("falha inesperada")
}

A palavra-chave defer adiada a execução de uma função até o retorno da função atual, útil para limpeza de recursos.

Tags: go tipos-de-dados cadeias-de-caracteres ponteiros Arrays

Publicado em 7-23 18:10