Conteúdo
Funções
O que são?
Imagine que você queira executar uma atividade, como, por exemplo, fazer um miojo (grande salvador dos dias da preguiça). Um passo a passo simples para isso seria: pegar o alimento, cozinhar e servir, certo? Nesse fluxo, não há preocupação em como cada passo será feito, mas sabe-se que para conseguir o resultado desejado essas etapas devem ser feitas.
Essa abstração do que está sendo feito em detalhes é exatamente o que uma função faz. Ou seja, dada uma certa entrada (podendo ser nenhuma), executa-se ações que levam a um resultado desejado, podendo ou não ter saídas.
Utilizar funções facilita muito o dia a dia de quem desenvolve, pois com elas conseguimos:
Quebrar problemas grandes em problemas menores
Tornar o código mais fácil de entender
Reutilizar código
Por isso, use e abuse sempre que possível, e fizer sentido, de funções \o/
Exemplo: função soma
package main
import (
"fmt"
)
func main() {
s := Soma(2,3)
fmt.Println(s)
}
// Soma recebe dois números inteiros positivos (entradas), realiza sua
//soma (ações) e retorna o resultado (saída).
func Soma(a int, b int) int {
return a + b
}
Sintaxe:
No exemplo acima, tivemos contato com a sintaxe de Go para declaração de funções, onde:
func representa a palavra chave para iniciar declaração de função
Soma é o nome da função, obedece a máxima de quando iniciar com maiúscula é visível fora do
package
, e com minúscula apenas dentro(a int, b int) são os parâmetros, as entradas da função, que seguem a sintaxe <nome> <tipo>, sempre separados por vírgula dentro do parênteses
int representa o tipo do retorno
{}, as chaves, são utilizadas para definir o escopo da função, onde ela começa e termina
return, é a palavra chave que utilizamos para retornar as saídas quando existe um retorno declarado
Tendo em mente essa sintaxe, aprofundaremos a seguir nos argumentos, e em seguida no retorno
Parâmetros de uma função em Go
Conforme dito anteriormente, os parâmetros da função são declarados logo após do nome na sintaxe para declaração de funções, e cada parâmetro por padrão segue a convenção <nome> <tipo>, sempre separados por vírgula dentro dos parênteses.
O que ainda não foi dito é que Go nos dá um açúcar sintático para facilitar nossa vida quando temos variáveis de um mesmo tipo. Dessa forma, o cabeçalho do exemplo anterior mudaria:
De:
func Soma(a int, b int) int { }
Para:
func Soma(a, b int) int { }
Além disso, como um recurso poderosíssimo da linguagem, temos ponteiros entre os tipos, o que nos proporciona a possibilidade de trabalhar com o próprio valor recebido como argumento da função, e não uma cópia.
Exemplo: funções SomaDoisPonteiro e SomaDois
package main
import (
"fmt"
)
func main() {
a := 2
b := 2
c := 2
SomaDoisPont(&a) // Como passamos a refêrencia (ponteiro) ao número, funcionará
SomaDois(b) // Como não passamos a referência e não pegamos o retorno, não funcionará
c = SomaDois(c) // Como pegamos o retorno, funcionará
fmt.Printf("a:%d, b:%d, c:%d", a, b, c)
}
// SomaDoisPonteiro recebe uma referência (ponteiro) para um número qualquer
// e adiciona dois a ele.
func SomaDoisPonteiro(n *int) {
*n = Soma(*n, 2)
}
// SomaDois recebe um número qualquer, adiciona dois a ele e retorna o resultado.
func SomaDois(n int) int {
n = Soma(n, 2)
return n
}
// Soma recebe dois números inteiros positivos (entradas), realiza sua soma (ações)
//e retorna o resultado (saída).
func Soma(a, b int) int {
return a + b
}
Retornos de uma função em Go
Talvez você não tenha reparado, mas nossa função Soma()
não obedece à regra de negócio estipulada a ela. Afinal, podemos passar números negativos como argumentos, e não recebemos nenhum erro sobre isso.
Dessa forma, passarems a fazer essa validação, e nossa função ficará assim:
package main
import (
"fmt"
)
func main() {
s, err := Soma(3, 1)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(s)
}
s, err = Soma(-3, 1)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(s)
}
}
// Soma recebe dois números inteiros positivos (entradas), realiza sua soma (ações)
// e retorna o resultado e um erro (saída).
func Soma(a, b int) (int, error) {
if a <= 0 || b <= 0 {
return 0, fmt.Errorf("todas as entradas precisam ser positivas, favor avaliar e tentar novamente")
}
return a + b, nil
}
Como é possível perceber no código acima, em Go temos a possibilIdade de ter mais de uma saída de uma função, obedecendo uma sintaxe parecida com a de entradas.
Inclusive, esse é um “padrão” muito importante e bem comum de se ver no mundo Go para tratamento de erros.
Bônus: funções variádicas
Nossa função Soma()
já tem um resultado muito bom e conciso, mas pra ficar melhor ainda queremos poder somar qualquer quantidade de números, não apenas dois como viemos fazendo. E isso é possível com um recurso poderosíssimo, as chamadas funções variádicas, presentes em Go e em outras linguagens.
Com esse recurso, conseguimos receber um número qualquer de argumentos de um dado tipo, na forma de um iterável. Vejamos o exemplo a seguir com nossa função Soma()
refatorada, em um caso de erro e um caso de sucesso.
package main
import (
"fmt"
)
func main() {
soma1, err1 := Soma(1, -2, 3, 4)
if err1 != nil {
fmt.Println("erro: ", err1)
} else {
fmt.Println("soma: ", soma1)
}
soma2, err2 := Soma(1, 2, 3, 4)
if err2 != nil {
fmt.Println("erro: ", err2)
} else {
fmt.Println("soma: ", soma2)
}
}
// Soma recebe n números inteiros positivos (entradas), realiza sua soma (ações)
// e retorna o resultado (saída).
func Soma(numeros ...int) (int, error) {
var soma int
for _, numero := range numeros {
if numero <= 0 {
return 0, fmt.Errorf("número %v não é positivo, e não é aceito nessa operação",
numero)
}
soma += numero
}
return soma, nil
}
Outra forma de utilizar esse recurso é adicionando ...
após um conjunto de elementos, como no argumento passado para a função Soma()
no exemplo abaixo:
package main
import (
"fmt"
)
func main() {
numeros := []int{0, 2, 3, 4}
soma, err := Soma(numeros...)
if err != nil {
fmt.Println("erro: ", err)
return
}
fmt.Println("soma: ", soma)
}
// Soma recebe n números inteiros positivos (entradas), realiza sua soma (ações)
// e retorna o resultado (saída).
func Soma(numeros ...int) (int, error) {
var soma int
for _, numero := range numeros {
if numero <= 0 {
return 0, fmt.Errorf("número %v não é positivo, e não é aceito nessa operação",
numero)
}
soma += numero
}
return soma, nil
}
Last updated