Estruturas básicas de controle com GO

Estruturas básicas de controle com GO

O Go (ou golang) é uma linguagem criada em 2007 pela equipe de desenvolvimento do Google. Tinha como objetivo facilitar o desenvolvimento de sistemas sem a necessidade de se utilizar outras linguagens de programação.

Vamos ver neste artigo suas principais estruturas de controle, bem como a criação de funções.

O famoso olá mundo!

Normalmente, o primeiro exercício em uma linguagem desconhecida da gente é o "olá mundo". Apenas escrevemos código na nova linguagem que exibe essa mensagem.

Embora não pareça nada demais, é um indicativo de que o seu ambiente foi corretamente construído, para que você possa realmente aprender a nova ferramenta.

No caso do Go, é um pouco mais simples que outras linguagens, como Java por exemplo:

package main

import "fmt"

func main(){
        fmt.Println("Olá mundo Go!")
}

Para rodarmos esse programa por linha de comando, não precisamos compilá-lo antes. Basta que salvemos esse código num arquivo .go (olamundo.go, por exemplo):

$ go run olamundo.go
Olá mundo Go!

Declarar variáveis também é bem simples:

numero1 := 1

Nesse caso, estamos declarando uma variável chamada numero1, e atribuindo o valor 1 a ela. Note o operador de atribuição ( :=).

Essa atribuição foi feita logo abaixo da mensagem inicial:

package main

import "fmt"

func main(){
  fmt.Println("Olá mundo Go!")
  numero1 := 1
}

Vamos então rodar esse programa...ops!

$ go run olamundo.go
# command-line-arguments
./olamundo.go:8:2: numero1 declared and not used

Repare que declaramos uma variável, mas esta não é usada em nenhuma parte do sistema, o que faz com que o interpretador go lance um erro de compilação. Esse recurso é bem interessante, pois disciplina o programador a manter somente o código que ele precisa. O time de criação da linguagem justifica a inclusão dessa característica no FAQ da linguagem. Basicamente:

The presence of an unused variable may indicate a bug, while unused imports just slow down compilation, an effect that can become substantial as a program accumulates code and programmers over time. For these reasons, Go refuses to compile programs with unused variables or imports, trading short-term convenience for long-term build speed and program clarity.

Logo, verificamos que eles se preocuparam não somente com variáveis que não são usadas, mas também com imports desnecessários, que podem fazer com que o processo de compilação fique mais lento. A explicação completa pode ser vista em https://golang.org/doc/faq#unused_variables_and_imports

Para que possamos remover esse erro, devemos dar uma finalidade a essa variável. No nosso caso, vamos apenas imprimir seu valor:

package main

import "fmt"

func main(){
  fmt.Println("Olá mundo Go!")
  numero1 := 1
  fmt.Println(numero1)
}

E temos como saída:

$ go run olamundo.go
Olá mundo Go!
1

Nada muito inesperado, não é mesmo? Repare que, diferente de outras linguagens como Java por exemplo, a sintaxe é menos verbosa e burocrática. Não precisamos colocar ponto-e-vírgula no final de nossas instruções.

Podemos declarar outro número, e somarmos os 2, gerando um terceiro número:

package main

import "fmt"

func main(){
fmt.Println("Olá mundo Go!")
numero1 := 1
fmt.Println(numero1)
numero2 := 2
numero3 := numero1 + numero2
fmt.Println(numero3)
}

E se precisarmos comparar ambos os números, imprimindo quem é o maior? Teremos que comparar os números. Para isso, podemos usar instruções if/else e fazer as comparações:

if numero1 < numero2 {
   fmt.Println("O número 1 é menor que o número 2")
   } else if(numero1 == numero2){
       fmt.Println("Os números 1 e 2 são iguais")
   } else {
       fmt.Println("O número 1 é maior que o número 2")
 }

Repare que as instruções if podem ou não ter sua condicional entre parênteses. Normalmente elas são escritas sem os parênteses mesmo. Fiz aqui apenas para mostrar que é possível.

Podemos inclusive refatorar este código, de forma que tenhamos apenas uma instrução de impressão de mensagens para todos esses condicionais. Para isso, podemos declarar uma variável do tipo String:

var mensagem string

E atribuir valores a ela de acordo com as condicionais:

if numero1 < numero2 {
   mensagem = "O número 1 é menor que o número 2"
} else if(numero1 == numero2) {
   mensagem = "Os números 1 e 2 são iguais"
} else {
   mensagem = "O número 1 é maior que o número 2"
}
fmt.Println(mensagem)

Há alguns pontos a se considerar. Diferente da maioria das linguagens, a declaração de variáveis do Go começa com a palavra chave var, seguida do nome da variável. Não há necessidade de declarar o tipo, embora possa ser necessário numa variável como essa, que pode ser usada em diversos pontos da função, garantindo que qualquer atribuição a ela seja do tipo declarado.

Além disso, note como a atribuição de valores à variável mensagem foi feita. Agora não usamos mais o operador :=, mas apenas o = . Para o Go, quando inicializamos uma variável com um determinado valor (o caso dos números por exemplo) usamos o primeiro operador. Nos demais, o segundo.

Mas, e se precisarmos verificar todos os números divisíveis por 5 entre 0 e 100, por exemplo? Para isso, podemos usar um looping, juntamente com o if:

for i := 0; i <= 50; i ++ {
   if i % 5 == 0 {
      fmt.Println(i, " é um número divisível por 5")
    }
}

Repare que, assim como o if, o for também não precisa de parênteses. Esta característica, combinada com outras da linguagem, contribuem para tornar o código menos verboso.

Além disso, fizemos a concatenação entre o valor de i e uma string (com s minúsculo mesmo. Diferente de linguagens como Java por exemplo (e semelhante ao C#), string escreve-se com letra minúscula).

A saída desse código será:

$ go run olamundo.go
Olá mundo Go!
1
3
O número 1 é menor que o número 2
0  é um número divisível por 5
5  é um número divisível por 5
10  é um número divisível por 5
15  é um número divisível por 5
20  é um número divisível por 5
25  é um número divisível por 5
30  é um número divisível por 5
35  é um número divisível por 5
40  é um número divisível por 5
45  é um número divisível por 5
50  é um número divisível por 5

Agora que vimos as principais estruturas de controle em Go, vamos revisitar o código que já criamos:

package main

import "fmt"

func main(){
fmt.Println("Olá mundo Go!")

numero1 := 1
fmt.Println(numero1)

numero2 := 2
numero3 := numero1 + numero2
fmt.Println(numero3)

var mensagem string
if numero1 < numero2 {
   mensagem = "O número 1 é menor que o número 2"
} else if(numero1 == numero2) {
   mensagem = "Os números 1 e 2 são iguais"
} else {
   mensagem = "O número 1 é maior que o número 2"
}
fmt.Println(mensagem)

for i := 0; i <= 50; i ++ {
  if i % 5 == 0 {
   fmt.Println(i, " é um número divisível por 5")
  }
 }
}

Temos código que lida com tarefas diferentes. Podemos organizá-lo em funções.

Comecemos com nosso primeiro cenário: a soma de 2 números:

numero1 := 1
fmt.Println(numero1)
numero2 := 2
fmt.Println(soma2numeros(numero1, numero2))

A função soma2numeros está abaixo:

func soma2numeros(n1, n2 int) 
int {
   return n1 + n2
}

Como os argumentos da função são do mesmo tipo, podemos simplificar a declaração de tipos, especificando-o apenas uma vez. Além disso, de forma semelhante à declaração de variáveis, colocamos o retorno da função no final de sua assinatura. Essa maneira de declarar tipos, seja de variáveis ou de funções, é algo a se destacar no Go, visto que a maioria das linguagens coloca a declaração de tipo antes da variável ou da função.

Podemos criar também uma função para encapsular a verificação de qual número é maior. Essa não retornará nada. Apenas exibirá no console quem é o maior número. O código dessa função está abaixo:

func qualEhOMaiorNumero(n1, n2 int){

var mensagem string
if n1 < n2 {
   mensagem = "O número 1 é menor que o número 2"
} else if(n1 == n2) {
   mensagem = "Os números 1 e 2 são iguais"
} else {
   mensagem = "O número 1 é maior que o número 2"
}
fmt.Println(mensagem)
}

Como podemos ver, como ele não retorna nada, não colocamos nenhum tipo de retorno. Agora é só chamar a função no método main(), substituindo o código anterior por ela:

func main(){
fmt.Println("Olá mundo Go!")
numero1 := 1
fmt.Println(numero1)
numero2 := 2
fmt.Println(soma2numeros(numero1, numero2))
qualEhOMaiorNumero(numero1, numero2)
for i := 0; i <= 50; i ++ {
   if i % 5 == 0 {
   fmt.Println(i, " é um número divisível por 5")
  }
 }
}

Por último, vamos encapsular o código que verifica quais os números divisíveis por 5:

func numerosDivisiveisPor5Entre0e50(){
   for i := 0; i <= 50; i ++ {
     if i % 5 == 0 {
       fmt.Println(i, " é um número divisível por 5")
     } 
   }
}

E o nosso código final ficará assim:

package main

import "fmt"

func main(){
fmt.Println("Olá mundo Go!")
numero1 := 1
fmt.Println(numero1)

numero2 := 2
fmt.Println(soma2numeros(numero1, numero2))

qualEhOMaiorNumero(numero1, numero2)
numerosDivisiveisPor5Entre0e50()
}

func soma2numeros(n1, n2 int) int {
        return n1 + n2
}

func qualEhOMaiorNumero(n1, n2 int){
var mensagem string
if n1 < n2 {
  mensagem = "O número 1 é menor que o número 2"
} else if(n1 == n2) {
  mensagem = "Os números 1 e 2 são iguais"
} else {
  mensagem = "O número 1 é maior que o número 2"
}
 fmt.Println(mensagem)
}

func numerosDivisiveisPor5Entre0e50(){
   for i := 0; i <= 50; i ++ {
     if i % 5 == 0 {
       fmt.Println(i, " é um número divisível por 5")
     }
   }
}
Banner da Escola de Programação: Matricula-se na escola de Programação. Junte-se a uma comunidade de mais de 500 mil estudantes. Na Alura você tem acesso a todos os cursos em uma única assinatura; tem novos lançamentos a cada semana; desafios práticos. Clique e saiba mais!

Considerações finais

Vimos como criar estruturas básicas de controle em Go, tais como declaração de variáveis, if/else, loopings e funções. Com esses recursos, é possível a criação de programas simples em Go.

Entretanto, caso queira saber mais, há o livro Programando em Go, do Caio Filipini, disponível na Casa do Código.

E aqui na Alura temos alguns curso para iniciar sua carreira em GO.

Bons estudos e até a próxima!

Rodrigo Vieira Pinto
Rodrigo Vieira Pinto

Mestre em Engenharia de Software pelo IPT-SP (Instituto de Pesquisas Tecnológicas de São Paulo) e Pós-graduado em Engenharia de Software pela PUC-SP. Mais de 20 anos de experiência com desenvolvimento de sistemas em Java, PHP, Ruby e Go. Além de ser um amante de software bem escrito, curto muito classic rock, automobilismo e estudar História do Brasil.

Veja outros artigos sobre Programação