Tutorial - Conversor numérico em GoLang

Denis Santos
5 min readJul 1, 2017

--

É certo que em todo curso ou disciplina de algoritmo nós sempre aprendemos o arroz com feijão da linguagem de programação a ser estudada, isso para que possamos desenvolver a estrutura básica de qualquer algoritmo. Por isso resolvi criar um programa que converta um valor numérico de String para Float, nele teremos a oportunidade de explorar pontos importantes da linguagem Go.

Segue o fluxo do nosso programa:

  • Entrada: Recebe um valor obrigatório como argumento de entrada;
  • Processamento: Deve validar esse valor e se for possível, convertê-lo em um número;
  • Saída: Exibir uma mensagem dizendo se o valor é numérico ou não.

Apenas com esse simples algoritmo poderemos aprender 5 coisas importantes da linguagem Go, sendo elas:

1 — Trabalhar com argumentos e operações do sistema operacional;

2 —Entender listas;

3 — Tomar decisões com o operador condicional IF;

4 —Usar uma função de conversão;

5 — Tratamento de erro em Go.

O nosso programa:

package mainimport (
"fmt"
"strconv"
"os"
)
func main() {
checkNumber(getValue())
}
func getValue() string {
if len(os.Args)-1 < 1 {
fmt.Println("One arg is requerid for this program")
os.Exit(1)
}
value := os.Args[1]
return value
}
func checkNumber(value string) {
fValue, err := strconv.ParseFloat(value, 64)
if err != nil {
fmt.Printf("The value <%s> is not a number\n", value)
os.Exit(1)
}
fmt.Printf("The value <%f> is a valid number\n", fValue)
}

GitHub: https://github.com/denissys/go-tutorial-converter

Crie o arquivo de código-fonte no seu workspace, no meu exemplo vou chamar de floatconv.go:

../go/workspace/src/converter/floatconv.go

Acesse o diretório src do seu workspace, e vamos fazer algumas execuções passando valores numéricos válidos para o nosso programa:

go run converter/floatconv.go 1
go run converter/floatconv.go 22.4
go run converter/floatconv.go 13567788.22220921

Para os cenários válidos, teremos as seguintes saídas no terminal, indicando que são valores numéricos:

The value <1.000000> is a valid number
The value <22.400000> is a valid number
The value <13567788.222209> is a valid number

Agora vamos testar sem nenhum argumento e também passando valores não numéricos:

go run converter/floatconv.go
go run converter/floatconv.go asdf
go run converter/floatconv.go false

Para os cenários com erros, teremos as seguintes saídas no terminal, indicando o argumento obrigatório e em seguida que os valores não são numéricos:

One arg is required for this program
exit status 1
The value <asdf> is not a number
exit status 1
The value <false> is not a number
exit status 1

Entendendo o nosso programa por partes

1 - Trabalhar com argumentos e operações do sistema operacional

Repare que importamos o pacote "os", esse pacote tem funções importantes para interagir com o sistema operacional onde seu programa está hospedado. Esse pacote facilita a execução do seu programa em plataformas diferentes, ou seja, permite que ele seja multiplataforma. No nosso caso, usamos o pacote "os" para utilizar a função que captura o argumento passado na execução do nosso programa por linha de comando, podendo interagir com esse valor em nosso código por meios de algumas funções. Repare que na linha de comando, após o nome do arquivo do programa floatconv.go, nós passamos um valor numérico 123, esse é o argumento:

go run converter/floatconv.go 123

E no código abaixo, nós utilizamos a função Arg do pacote "os" para recuperar o valor 123 que foi passado como argumento, esse valor é atribuído na variável value:

value := os.Args[1]

Observe no código acima que na atribuição do valor na variável value não foi necessário especificar o tipo da variável (os.Args sempre recebe os valores como string pela linha de comando), para resolver o tipo da variável value o compilador saberá atribuir o tipo correto com base no dado (string, int, float, bool …).

Além disso, nós usamos a função Exit do pacote “os”, no nosso código o Exit interrompe a execução do programa nos casos onde determinamos um erro.

if len(os.Args)-1 < 1 {
fmt.Println("One arg is requerid for this program")
os.Exit(1)
}

A instrução os.Exit(1) recebe o valor 1 como argumento, isso indica para o sistema operacional que o programa foi finalizado com erro, se o valor do argumento fosse zero, indicaria uma execução finalizada normalmente (seguindo os padrões de programas Unix, leia mais aqui).

2 - Entender listas

Em Go existem dois tipos de listas, podendo ser um array que é uma lista de tamanho fixo, ou slices que são listas dinâmicas onde seu tamanho pode aumentar ou diminuir.

Obs.: Mais para frente farei um tutorial explorando e explicando com detalhes a diferença entre array e slices.

No nosso caso usamos o os.Args que é um slice, nele são armazenados os argumentos que foram passados por linha de comando na execução do nosso programa.

Usando a função len() nós conseguimos obter o tamanho da nossa lista len(os.Args), é importante saber que a primeira posição da lista tem o índice 0.

if len(os.Args)-1 < 1 {
...
}

Na instrução os.Args[1] nós usamos colchetes seguido da posição do índice para obter o valor armazenado nessa posição da lista.

value := os.Args[1]

Obs.: No nosso programa a posição 0 (zero) está ocupada com a informação da execução do programa que foi executado por linha de comando (os.Args[1] => /var/folders/fv/p7vn4fts1153tqh5956f40940000gn/T/go-build933283485/command-line-arguments/_obj/exe/floatconv), já o dado que passamos como argumento está na posição 1 (um) do índice da lista, ou seja, a nossa lista tem 2 elementos.

3 - Tomar decisões com o operador condicional IF

Nós usamos o operador condicional IF duas vezes no nosso código, sendo:

if len(os.Args)-1 < 1 { ... )if err != nil { ... )

Em Go apenas expressões do tipo bool, ou seja, expressões do tipo verdadeiro ou falso (true/false) podem ser utilizadas no operador condicional if, podendo receber uma variável ou função.

4 - Usar uma função de conversão

Para converter o valor do argumento que é string para float, nós usamos a função ParseFloat do pacote "strconv" (string conversion), esse pacote fornece muitos outros tipos de conversões de string para outros tipos de dados como decimal, float, bool.

fValue, err := strconv.ParseFloat(value, 64)

5 - Tratamento de erro em Go

Repare na instrução abaixo:

fValue, err := strconv.ParseFloat(value, 64)

Viu que além de declarar a variável fValue, foi declarado junto a variável err (erro de conversão), ou seja, a função retorna dois valores. Isso pode parecer confuso, estranho, diferente, mas temos que lembrar que Go é uma linguagem funcional e com novos paradigmas, e esse é um de seus bons recursos. Nesse casso a variável err pode retornar um nil (nulo), se isso ocorrer é porque a conversão não retornou nenhum erro, caso contrário é porque um erro ocorreu na conversão do valor.

fValue, err := strconv.ParseFloat(value, 64)
if err != nil {
fmt.Printf("The value <%s> is not a number\n", value)
os.Exit(1)
}

Em particular, achei ótimo a maneira Go de tratar erros, não precisamos lidar com dezenas de formas de trabalhar com uma ou mais exceções, no inicio pode até parecer verboso, mas pelos códigos que estou desenvolvendo e também os que venho acompanhando, se torna mais simples de lidar com erros em Go. No Java por exemplo, sempre dedico um certo tempo para entender a arquitetura de tratamento de erros que cada um definiu em seu projeto, como também devemos ficar atentos quando é usada uma RuntimeException.

O próximo passo será fazer o teste unitário em Go:

Código bom tem que ter cobertura de teste unitário, isso não é diferente em Go, então leia o próximo tutorial onde aprenderemos a testar o nosso algoritmo conversor numérico: <assim que eu finalizar o tutorial publicarei o link aqui>

--

--

Denis Santos

Não ignore as suas ideias, a menor delas pode ser a mais importante.