Em Go, os tipos básicos formam a base para toda a manipulação de dados. Eles incluem números inteiros e de ponto flutuante, strings e runes para texto, e booleanos para lógica. Entender esses tipos e como convertê-los explicitamente é essencial para escrever código correto e eficiente.

Diferente de algumas linguagens, Go é fortemente tipada e não realiza conversões implícitas entre tipos. Isso evita bugs sutis, mas exige que o programador seja explícito nas transformações. Vamos explorar cada um desses tipos com exemplos práticos.

Inteiros e floats

Go oferece vários tamanhos de inteiros com e sem sinal: int8, int16, int32, int64, uint8, uint16, uint32, uint64. Além disso, int e uint têm tamanho dependente da plataforma (32 ou 64 bits). Para números de ponto flutuante, temos float32 e float64 (e complex64/complex128 para números complexos).

Exemplo de declaração e uso:

package main

import "fmt"

func main() {
    var a int = 10
    var b int8 = 20
    var c int64 = 30
    var d uint = 40
    var e float32 = 3.14
    var f float64 = 2.71828

    fmt.Println(a, b, c, d, e, f)
}

É importante notar que você não pode misturar tipos diferentes em expressões sem conversão explícita. Por exemplo, a + b causará um erro de compilação porque a é int e b é int8.

Strings e runes

Em Go, strings são sequências imutáveis de bytes (UTF-8). Elas são declaradas com aspas duplas. Runes representam um único caractere Unicode e são do tipo rune (que é um alias para int32). Runes são declaradas com aspas simples.

Exemplo:

package main

import "fmt"

func main() {
    var s string = "Olá, mundo!"
    var r rune = 'O'
    fmt.Println(s, r)
    // Acessando bytes e runes
    for i, c := range s {
        fmt.Printf("byte %d: %c (rune %d)\n", i, c, c)
    }
}

Strings podem ser concatenadas com + e comparadas com ==. Runes são úteis para trabalhar com caracteres Unicode de forma individual.

Booleanos

O tipo booleano em Go é bool e pode ser true ou false. Operadores lógicos como &&, || e ! são usados para combinar valores booleanos.

Exemplo:

package main

import "fmt"

func main() {
    var ativo bool = true
    var ok bool = false
    if ativo && !ok {
        fmt.Println("Ativo e não ok")
    }
}

Go não permite conversão implícita de booleanos para inteiros ou vice-versa. Você deve usar explicitamente uma condição.

Conversões explícitas

Para converter entre tipos numéricos, use a sintaxe T(v), onde T é o tipo de destino e v é o valor. Para strings e runes, há funções como string() e []rune(). Conversões podem perder precisão ou causar overflow, então tome cuidado.

Exemplos:

package main

import "fmt"

func main() {
    var x int = 42
    var f float64 = float64(x) // 42.0
    var u uint = uint(f)       // 42
    var s string = string(rune(65)) // "A"
    fmt.Println(x, f, u, s)
    // Conversão de string para slice de bytes
    b := []byte("Hello")
    fmt.Println(b)
}

Lembre-se: conversões entre tipos não relacionados (como int para string) podem não fazer o que você espera. Sempre verifique a documentação.

Boas práticas

Prefira usar tipos com tamanho explícito quando a portabilidade for importante (ex.: int64 para IDs). Use float64 para cálculos de precisão dupla. Evite conversões desnecessárias e sempre trate possíveis perdas de dados. Para strings, lembre-se de que a iteração com range retorna runes, não bytes.

Referências

Exercícios

  1. Declare uma variável idade como int e atribua 25. Depois converta para float64 e imprima.
  2. ✓ Resposta:
    package main
    
    import "fmt"
    
    func main() {
        var idade int = 25
        var f float64 = float64(idade)
        fmt.Println(f)
    }
  3. Escreva um programa que declare uma string nome com seu nome e imprima o número de runes (caracteres Unicode) que ela contém.
  4. ✓ Resposta:
    package main
    
    import "fmt"
    
    func main() {
        nome := "João"
        runes := []rune(nome)
        fmt.Println(len(runes))
    }
  5. Crie uma variável booleana chovendo e atribua true. Use uma estrutura condicional para imprimir "Leve guarda-chuva" se for verdadeiro.
  6. ✓ Resposta:
    package main
    
    import "fmt"
    
    func main() {
        chovendo := true
        if chovendo {
            fmt.Println("Leve guarda-chuva")
        }
    }
  7. Converta um inteiro 65 para string e imprima o resultado. Explique o que acontece.
  8. ✓ Resposta:
    package main
    
    import "fmt"
    
    func main() {
        var n int = 65
        s := string(rune(n))
        fmt.Println(s) // Imprime "A"
    }

    A conversão de um inteiro para string usando string(rune(n)) interpreta o inteiro como um ponto de código Unicode e retorna a string correspondente. 65 é o código de 'A'.

  9. Escreva um programa que converta um float64 para int e observe a perda de precisão.
  10. ✓ Resposta:
    package main
    
    import "fmt"
    
    func main() {
        var pi float64 = 3.14159
        var i int = int(pi)
        fmt.Println(i) // Imprime 3, truncado
    }