patterngoMajor
Fibonacci generator with Golang
Viewed 0 times
withgolangfibonaccigenerator
Problem
This is my Fibonacci generator:
It's working, but I don't know how I can improve it, so I'd like more expert approaches to solving it.
package main
import "fmt"
func main() {
for i, j := 0, 1; j < 100; i, j = i+j,i {
fmt.Println(i)
}
}It's working, but I don't know how I can improve it, so I'd like more expert approaches to solving it.
Solution
Your code is quite nice, and can't really be improved. However, let's put the “generator” back into the code.
Go has channels which can be used to write elegant generators/iterators. We spawn of a goroutine that fills the channel with the fibonacci sequence. The main thread then takes as many fibonacci numbers as it needs.
So let's write a function
We return a
Next, we spawn a goroutine. This contains your code, but instead of printing the numbers, we fill the channel with them. Note that the generator does not have a termination condition.
The unusual syntax
is the standard way to start a goroutine. Because the function literal is a closure over the channel
Our
That is, we create a new generator, and then pull the first 12 values from the channel. We cannot write
As I said, we can have multiple generators concurrently:
Output:
Go has channels which can be used to write elegant generators/iterators. We spawn of a goroutine that fills the channel with the fibonacci sequence. The main thread then takes as many fibonacci numbers as it needs.
So let's write a function
fib_generator that returns a channel to the fibonacci sequence:func fib_generator() chan int {
c := make(chan int)
go func() {
for i, j := 0, 1; ; i, j = i+j,i {
c <- i
}
}()
return c
}We return a
chan int. Here, we use an unbuffered channel. You may want to introduce a bit of buffering, e.g. make(chan int, 7).Next, we spawn a goroutine. This contains your code, but instead of printing the numbers, we fill the channel with them. Note that the generator does not have a termination condition.
The unusual syntax
go func() { ... }()is the standard way to start a goroutine. Because the function literal is a closure over the channel
c, we can run multiple generators concurrently.Our
main will look likefunc main() {
c := fib_generator()
for n := 0; n < 12 ; n++ {
fmt.Println(<- c)
}
}That is, we create a new generator, and then pull the first 12 values from the channel. We cannot write
for i := range c { ... }, because the fibonacci generator does not terminate.As I said, we can have multiple generators concurrently:
func main() {
c1 := fib_generator()
c2 := fib_generator()
// read first 12 numbers from 1st channel
for n := 0; n < 10 ; n++ { fmt.Print(" ", <- c1) }
fmt.Println()
// read first 12 numbers from 2nd channel. The same.
for n := 0; n < 10 ; n++ { fmt.Print(" ", <- c2) }
fmt.Println()
// read next 5 numbers from 1st channel.
for n := 0; n < 5 ; n++ { fmt.Print(" ", <- c1) }
fmt.Println()
}Output:
0 1 1 2 3 5 8 13 21 34
0 1 1 2 3 5 8 13 21 34
55 89 144 233 377Code Snippets
func fib_generator() chan int {
c := make(chan int)
go func() {
for i, j := 0, 1; ; i, j = i+j,i {
c <- i
}
}()
return c
}go func() { ... }()func main() {
c := fib_generator()
for n := 0; n < 12 ; n++ {
fmt.Println(<- c)
}
}func main() {
c1 := fib_generator()
c2 := fib_generator()
// read first 12 numbers from 1st channel
for n := 0; n < 10 ; n++ { fmt.Print(" ", <- c1) }
fmt.Println()
// read first 12 numbers from 2nd channel. The same.
for n := 0; n < 10 ; n++ { fmt.Print(" ", <- c2) }
fmt.Println()
// read next 5 numbers from 1st channel.
for n := 0; n < 5 ; n++ { fmt.Print(" ", <- c1) }
fmt.Println()
}0 1 1 2 3 5 8 13 21 34
0 1 1 2 3 5 8 13 21 34
55 89 144 233 377Context
StackExchange Code Review Q#28386, answer score: 20
Revisions (0)
No revisions yet.