Tutorial

Como converter tipos de dados em Go

GoDevelopment

Introdução

Na linguagem Go, os tipos de dados são usados para classificar um tipo específico de dados, determinando os valores que você pode atribuir ao tipo e às operações que você pode realizar com ela. Ao programar, há momentos em que você terá que converter valores entre os no tipos, no intuito de manipular tais valores de maneira diferente. Por exemplo, talvez você necessite concatenar valores numéricos com strings, ou representar casas decimais em números que foram inicializados como valores de número inteiro. Com frequência, o tipo de dados da string é automaticamente atribuído aos dados gerados pelo usuário, mesmo se consistirem em números. Para realizar operações matemáticas nessa entrada, por exemplo, você teria que converter a string para um tipo de dados numéricos.

Como o Go é uma linguagem de tipagem estática, os tipos de dados são vinculados às variáveis e não aos valores. Isso significa que, se você definir uma variável como int, ela só poderá ser uma int; você não poderá atribuir-lhe uma string sem converter o tipo de dados da variável. A natureza estática dos tipos de dados em Go confere ainda mais importância ao aprendizado das maneiras de convertê-los.

Este tutorial explicará sobre como converter números e strings, além de fornecer exemplos para ajudar você a se familiarizar com os diferentes casos de uso.

Convertendo os tipos de número

O Go tem vários tipos numéricos dentre os quais escolher. Em princípio, eles se dividem em dois tipos gerais: os números inteiros e os números de ponto flutuante.

Existem várias situações nas quais você pode querer converter entre os tipos numéricos. Converter entre diferentes tamanhos de tipos numéricos pode ajudar a otimizar o desempenho em relação a tipos específicos de arquiteturas de sistema. Se você tiver um número inteiro de outra parte do seu código e quiser fazer uma divisão com ele, você pode querer converter o número inteiro em um float, a fim de preservar a precisão da operação. Além disso, trabalhar com durações do tempo geralmente envolve uma conversão de número inteiro. Para resolver essas situações, o Go tem a função de conversões de tipo integrada para a maioria dos tipos numéricos.

Convertendo entre os tipos de inteiros

A linguagem Go tem muitos tipos de dados inteiros dentre os quais escolher. Quando escolher um e não o outro, normalmente, é uma questão de desempenho; no entanto, haverá momentos em que você precisará converter de um tipo de número inteiro para outro. Por exemplo, o Go gera valores numéricos de maneira automática, como int, o qual pode não corresponder ao valor de sua entrada. Se o valor de sua entrada fosse um int64, não seria possível usar números int e int64 na mesma expressão matemática até que você convertesse seus respectivos tipos de dados para que correspondessem.

Suponha que você tem um int8 e que precisa convertê-lo em um int32. Você pode fazer isso encapsulando-o na conversão de tipo int32():

var index int8 = 15

var bigIndex int32

bigIndex = int32(index)

fmt.Println(bigIndex)
Output
15

Esse bloco de código define index como um tipo de dados int8 e bigIndex como um tipo de dados int32. Para armazenar o valor index no bigIndex, ele converte o tipo de dados para um int32. Isso é feito encapsulando-se conversão de int32() em torno da variável index.

Para verificar seus tipos de dados, você poderia usar a instrução fmt.Printf e o verbo %T com a seguinte sintaxe:

fmt.Printf("index data type:    %T\n", index)
fmt.Printf("bigIndex data type: %T\n", bigIndex)
Output
index data type: int8 bigIndex data type: int32

Como esse procedimento usa o verbo %T, a instrução de impressão produz o tipo para a variável e não o valor real da variável. Desta forma, você pode confirmar o tipo de dados convertido.

Você pode, ainda, converter de um número inteiro de bit maior para um número inteiro de bit menor.

var big int64 = 64

var little int8

little = int8(big)

fmt.Println(little)
Output
64

Lembre-se de que ao converter números inteiros, haveria a possibilidade de você exceder o valor máximo do tipo do dados e do wraparound:

var big int64 = 129
var little = int8(big)
fmt.Println(little)
Output
-127

Um wraparound ocorre quando um valor é convertido para um tipo de dados de tamanho pequeno demais para contê-lo. No exemplo anterior, o tipo de dados de 8 bits int8 não tinha espaço suficiente para conter a variável de 64 bits big. Ao se converter de um tipo de dados de valor maior para um tipo de dados de valor menor, é necessário sempre tomar cuidado para não truncar acidentalmente os dados.

Convertendo os números inteiros em floats

A conversão de números inteiros em floats em Go é parecida com a conversão de um tipo de número inteiro para outro. Você pode usar as conversões de tipo integradas, fazendo com que os tipos float64() ou float32() envolvam o número inteiro que você estiver convertendo:

var x int64 = 57

var y float64 = float64(x)

fmt.Printf("%.2f\n", y)
Output
57.00

Esse código declara uma variável x do tipo int64 e inicializa seu valor em 57.

var x int64 = 57

Com a conversão do float64() envolvendo a variável x, o valor de 57 será convertido a um valor float de 57,00.

var y float64 = float64(x)

O verbo de impressão %2f diz ao fmt.Printf para formatar o float com dois decimais.

Também é possível usar esse processo em uma variável. O código a seguir declara um f igual a 57 e, em seguida, imprime o novo float:

var f float64 = 57
fmt.Printf("%.2f\n", f)
Output
57.00

Você pode converter inteiros em floats usando tanto o float32() como o float64(). A seguir, você irá aprender como converter de floats em inteiros.

Convertendo floats em inteiros

O Go pode converter os floats em inteiros, mas o programa perderá a precisão do float.

Envolver os floats em int(), ou um de seus tipos de dados de arquitetura independente, funciona de maneira similar à que usou para converter de um tipo inteiro a outro tipo. É possível adicionar um número de ponto flutuante dentro dos parênteses para convertê-lo em um número inteiro:

var f float64 = 390.8
var i int = int(f)

fmt.Printf("f = %.2f\n", f)
fmt.Printf("i = %d\n", i)
Output
f = 390.80 i = 390

Esta sintaxe converteria o float 390.8 no número inteiro 390, eliminando a casa decimal.

Você também pode usar essa técnica com as variáveis. O código a seguir declara b igual a 125.0 e c igual a 390.8; depois, o código os imprime como inteiros. A declaração de variável curta (:=) abrevia a sintaxe:

b := 125.0
c := 390.8

fmt.Println(int(b))
fmt.Println(int(c))
Output
125 390

Ao converter os floats em inteiros com o tipo int(), o Go corta a casa decimal e os números do float que restam são usados para criar um inteiro. Note que, embora talvez você queira arredondar 390,8 para 391, o Go não fará isso através do tipo int(). Em vez disso, ele vai simplesmente eliminar a casa decimal.

Números convertidos através de divisão

Ao dividir tipos inteiros em Go, o resultado também será um tipo inteiro, com o modulus (módulo), ou o resto, removido.

a := 5 / 2
fmt.Println(a)
Output
2

Se, ao dividir, qualquer um dos tipos de número for um float, todos os tipos serão automaticamente declarados como float:

    a := 5.0 / 2
    fmt.Println(a)
Output
2.5

Isso divide o float 5.0 pelo número inteiro 2, tendo como resposta 2.5, que é um float que retém a precisão decimal.

Nesta seção, você converteu entre os tipos de dados numéricos diferentes, incluindo tamanhos diferentes de inteiros e os números de ponto flutuante. A seguir, você irá aprender como converter entre números e strings.

Convertendo com as strings

Uma string é uma sequência de um ou mais caracteres (letras, números ou símbolos). As strings são uma forma comum de dados em programas de computador. Você pode precisar converter strings em números e números em strings com bastante frequência, especialmente quando estiver incluindo dados gerados pelo usuário.

Convertendo números em strings

Você pode converter números em strings, usando o método strconv.Itoa do pacote strconv da biblioteca padrão do Go. Se passar um número ou uma variável entre os parênteses do método, aquele valor numérico será convertido em um valor de string.

Primeiro, vamos examinar a conversão de de números inteiros. Para converter o inteiro 12 em um valor de string, você pode enviar o número o 12 para o método strconv.Itoa:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    a := strconv.Itoa(12)
    fmt.Printf("%q\n", a)
}

Durante a execução deste programa, você receberá o seguinte resultado:

Output
"12"

As aspas ao redor do número 12 significam que o número já não é mais um inteiro, mas sim um valor de string.

Você usou o operador de instrução := tanto para declarar uma nova variável com o nome de a, como para atribuir o valor retornado pela função strconv.Itoa(). Neste caso, você atribuiu o valor 12 para sua variável. Você também usou o verbo %q na função fmt.Printf, o qual diz à função para citar a string fornecida.

Com variáveis, você pode começar a ver como é prático converter inteiros em strings. Digamos que você queira monitorar o progresso diário dos usuários na programação, além do número de linhas que eles estão inserindo a cada vez no código que estão escrevendo. Você quer mostrar esse feedback para o usuário. Para tanto, você vai imprimir os valores de string e inteiro ao mesmo tempo:

package main

import (
    "fmt"
)

func main() {
    user := "Sammy"
    lines := 50

    fmt.Println("Congratulations, " + user + "! You just wrote " + lines + " lines of code.")
}

Ao executar este código, você receberá o seguinte erro:

Output
invalid operation: ("Congratulations, " + user + "! You just wrote ") + lines (mismatched types string and int)

Você não pode concatenar strings e inteiros em Go, de modo que terá que converter a variável lines para se tornar um valor de string:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    user := "Sammy"
    lines := 50

    fmt.Println("Congratulations, " + user + "! You just wrote " + strconv.Itoa(lines) + " lines of code.")
}

Agora, quando executar o código, receberá o resultado a seguir, parabenizando o seu usuário pelo progresso alcançado:

Output
Congratulations, Sammy! You just wrote 50 lines of code.

Se você tiver planos de converter um float em uma string, em vez de um inteiro em uma string, você seguirá passos e formatos semelhantes. Ao enviar um float para o método fmt.Sprint, a partir do pacote fmt na biblioteca Go padrão, será retornado um valor de string do float. Você pode usar o valor do float em si ou uma variável:

package main

import (
    "fmt"
)

func main() {
    fmt.Println(fmt.Sprint(421.034))

    f := 5524.53
    fmt.Println(fmt.Sprint(f))
}
Output
421.034 5524.53

Você pode fazer um teste para se assegurar de que está correto, fazendo a concatenação com uma string:

package main

import (
    "fmt"
)

func main() {
    f := 5524.53
    fmt.Println("Sammy has " + fmt.Sprint(f) + " points.")
}
Output
Sammy has 5524.53 points.

Agora, você pode certificar-se que o float foi devidamente convertido em uma string porque a concatenação foi realizada sem erros.

Convertendo strings em números

As strings podem ser convertidas em números, usando-se o pacote strconv da biblioteca padrão do Go. O pacote strconv tem funções para converter tipos de números inteiros e float. Essa é uma operação muito comum quando o programa aceita entradas do usuário. Por exemplo, se você tiver um programa que pede a idade de uma pessoa e a pessoa digita uma resposta, essa resposta é capturada como uma string. Na sequência, você teria que converter a idade em um int para, assim, fazer qualquer operação matemática com ela.

Se sua string não tiver casas decimais, você provavelmente vai querer convertê-la em um número inteiro, usando a função strconv.Atoi. Se você souber que usará o número como um float, usaria a strconv.ParseFloat.

Vamos usar o exemplo do usuário Sammy, monitorando as linhas de código escritas a cada dia. Você pode querer manipular esses valores com operações matemáticas, no intuito de dar um feedback mais interessante para o usuário. Porém, no momento, tais valores estão armazenados em strings:

package main

import (
    "fmt"
)

func main() {
    lines_yesterday := "50"
    lines_today := "108"

    lines_more := lines_today - lines_yesterday

    fmt.Println(lines_more)
}
Output
invalid operation: lines_today - lines_yesterday (operator - not defined on string)

Como os dois valores numéricos foram armazenados em strings, você recebeu um erro. O operando - para a subtração não é um operando válido para dois valores de string.

Modifique o código para incluir o método strconv.Atoi() que converterá as strings em inteiros, permitindo, assim, que você faça operações matemáticas com os valores que eram originalmente strings. Como há uma falha em potencial ao se converter uma string em um inteiro, você tem que verificar se há algum erro. Você pode usar uma instrução if para verificar se sua conversão foi bem-sucedida.

package main

import (
    "fmt"
    "log"
    "strconv"
)

func main() {
    lines_yesterday := "50"
    lines_today := "108"

    yesterday, err := strconv.Atoi(lines_yesterday)
    if err != nil {
        log.Fatal(err)
    }

    today, err := strconv.Atoi(lines_today)
    if err != nil {
        log.Fatal(err)
    }
    lines_more := today - yesterday

    fmt.Println(lines_more)
}

Como é possível que uma string não seja um número, o método strconv.Atoi() retornará tanto o tipo convertido, quanto um erro em potencial. Ao converter a partir de lines_yesterday com a função strconv.Atoi, você tem que verificar o valor retornado err para assegurar que o valor foi convertido. Se o err não for nil, significa que o strconv.Atoi não conseguiu converter o valor string em um inteiro. Nesse exemplo, você usou uma instrução if para verificar quanto a algum erro. Se um erro foi retornado, você usou o log.Fatal para registrar o erro e sair do programa.

Ao executar o código anterior, você receberá:

Output
58

Agora, tente converter uma string que não seja um número:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    a := "not a number"
    b, err := strconv.Atoi(a)
    fmt.Println(b)
    fmt.Println(err)
}

Você receberá o seguinte erro:

Output
0 strconv.Atoi: parsing "not a number": invalid syntax

Como o b foi declarado, mas o strconv.Atoi não conseguiu fazer uma conversão, o valor nunca foi atribuído a b. Note que o b tem o valor de 0. Isso acontece porque o Go tem valores padrão referidos como valores de zero em Go. O strconv.Atoi fornece um erro que descreve porque ele também não conseguiu converter a string.

Convertendo strings e bytes

As strings em Go são armazenadas em uma fatia de bytes. Na linguagem Go, você pode converter entre uma fatia de bytes e uma string encapsulando-a nas conversões correspondentes de []byte() e string():

package main

import (
    "fmt"
)

func main() {
    a := "my string"

    b := []byte(a)

    c := string(b)

    fmt.Println(a)

    fmt.Println(b)

    fmt.Println(c)
}

Aqui,você armazenou um valor de string em a; depois, converteu-o em uma fatia de bytes b; na sequência, converteu a fatia de bytes de volta em uma string, como c. Em seguida, imprimiu a, b e c na tela:

Output
my string [109 121 32 115 116 114 105 110 103] my string

A primeira linha do resultado é a string original my string. A segunda linha imprimida é a fatia byte que compõe a string original. A terceira linha mostra que a fatia byte pode ser convertida de volta com segurança em uma string e imprimida.

Conclusão

Este tutorial do Go demonstrou como converter vários dos tipos de dados nativos importantes em outros tipos de dados, principalmente através de métodos integrados. Poder converter tipos de dados em Go permitirá que você faça coisas como aceitar as entradas de usuários e realizar operações matemáticas entre os diferentes tipos de números. Mais tarde, quando estiver usando o Go para escrever programas que aceitam dados de várias fontes diferentes como bancos de dados e APIs, você usará esses métodos de conversão para garantir que possa atuar sobre os seus dados. Também será possível otimizar o armazenamento, convertendo dados em tipos de dados menores.

Se você quiser uma análise mais profunda dos tipos de dados em Go, verifique nosso artigo Entendendo tipos de dados em Go.

Creative Commons License