Médio Go

Gerador de Fibonacci

Enunciado

Implemente uma função geradorFibonacci que retorna uma closure. A closure deve gerar o próximo número da sequência de Fibonacci a cada chamada, começando em 0 e 1. No main, imprima os 10 primeiros números.

Requisitos

  • A função geradorFibonacci retorna func() int.
  • A closure mantém os dois últimos valores da sequência.
  • Os 10 primeiros números são: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.

Código inicial

package main

import "fmt"

// geradorFibonacci retorna uma closure que gera números de Fibonacci.
func geradorFibonacci() func() int {
	// implemente aqui
	return nil
}

func main() {
	// crie o gerador e imprima os 10 primeiros números
}

Saída esperada

0
1
1
2
3
5
8
13
21
34
Ver dica

Mantenha duas variáveis a e b (inicialmente 0 e 1). A cada chamada, retorne a e atualize a, b = b, a+b.

Mostrar solução
package main

import "fmt"

// geradorFibonacci retorna uma closure que gera a sequência de Fibonacci.
func geradorFibonacci() func() int {
	a, b := 0, 1 // estado inicial
	return func() int {
		prox := a          // guarda o valor a ser retornado
		a, b = b, a+b      // atualiza para o próximo par
		return prox
	}
}

func main() {
	fib := geradorFibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(fib())
	}
}

Passo a passo

  1. Dentro de geradorFibonacci, declaramos a, b := 0, 1. Essas variáveis representam os dois últimos números da sequência.
  2. Retornamos uma closure que captura a e b.
  3. Na closure, prox := a guarda o valor atual antes de atualizar.
  4. a, b = b, a+b faz a troca: a recebe o antigo b, e b recebe a soma. Isso avança a sequência.
  5. Retornamos prox, que é o número Fibonacci da vez.
  6. No main, chamamos fib() 10 vezes e imprimimos cada resultado.
  7. A sequência começa em 0 e segue corretamente até 34.

Por que funciona

A closure mantém o estado de a e b entre chamadas. Cada chamada atualiza esses valores de forma atômica (para uso single-thread) e retorna o número correto. O uso de atribuição múltipla a, b = b, a+b evita a necessidade de uma variável temporária.

Erros comuns

  • Não guardar o valor antes de atualizar: se fizer a, b = b, a+b; return a, o primeiro retorno seria 1 em vez de 0.
  • Atualizar b antes de a: b = a + b; a = b - a é confuso e propenso a erros; prefira a atribuição múltipla.
  • Usar int e estourar: para muitos números, int pode estourar; mas para 10 termos é seguro.

Outra forma de resolver

Usar um slice pré-computado não é uma closure, mas resolve o mesmo problema sem estado persistente. A closure é preferível quando se quer gerar sob demanda, sem alocar memória para toda a sequência.

Saída esperada

0
1
1
2
3
5
8
13
21
34