0

Generators are rather familiar objects in Python. Generators supply data on demand. Using Go you can create a generator with a goroutine and a channel. Here the goroutine is an anonymous function within a function, simple to implement.

// generator_fib4.go
//
// use a channel to simulate a generator
//
// channels are the pipes that connect concurrent goroutines
// send to channel syntax is "chan <- v"
// receive from channel syntax is "v, status := <-chan"
// (data flows in the direction of the arrow)
// receive status is true unless closed with closed(chan)
//
// more detailed info at:
// http://golang.org/ref/spec#Making_slices_maps_and_channels
// https://golang.org/ref/spec#Receive_operator
// online play at:
// http://play.golang.org/p/8CrOj6lmKe
//
// tested with Go version 1.4.2   by vegaseat  3may2015

package main

import "fmt"

// generator using a channel and a goroutine
func fib(n int) chan int {
	// create a channel
	c := make(chan int)
	// create an anonymous inner function
	// keyword "go" starts a goroutine
	go func() {
		x, y := 0, 1
		for k := 0; k < n; k++ {
			// send value x to the channel c
			c <- x
			// swap
			x, y = y, x+y
		}
		// close(c) sets the status of the channel c to false
		// and is needed by the for/range loop to end
		close(c)
	}()
	return c
}

func main() {
	fmt.Println("A Fibonacci generator via channel/goroutine:")
	// function fib() returns a channel
	// so fc would be of type "chan int"
	fc := fib(13)
	fmt.Printf("fc is type %T\n", fc)
	for k := range fc {
		fmt.Printf("%d  ", k)
	}
	fmt.Println()
}

/*
A Fibonacci generator via channel/goroutine:
fc is type chan int
0  1  1  2  3  5  8  13  21  34  55  89  144
*/
1
Contributor
1
Reply
19
Views
2 Years
Discussion Span
Last Post by vegaseat
1

This explains the generator action a little better ...

// generator_fib5.go
//
// use a channel to simulate a generator
//
// channels are the pipes that connect concurrent goroutines
// send to channel syntax is "chan <- v"
// receive from channel syntax is "v, status := <-chan"
// (data flows in the direction of the arrow)
// receive status is true unless closed with closed(chan)
//
// more detailed info at:
// http://golang.org/ref/spec#Making_slices_maps_and_channels
// https://golang.org/ref/spec#Receive_operator
// online play at:
// http://play.golang.org/p/8kwaqcYWFq
//
// tested with Go version 1.4.2   by vegaseat  4may2015

package main

import "fmt"

// generator using a channel and a goroutine
func fib(n int) chan int {
    // create a channel
    c := make(chan int)
    // create an anonymous inner function
    // keyword "go" starts a goroutine
    go func() {
        x, y := 0, 1
        for k := 0; k < n; k++ {
            // send value x to the channel c
            c <- x
            // swap
            x, y = y, x+y
        }
        // close(c) sets the status of the channel c to false
        // indicates that the channel is now empty
        close(c)
    }()
    return c
}

func main() {
    fmt.Println("A Fibonacci generator via channel/goroutine:")
    // function fib() returns a channel
    // so fc would be of type "chan int"
    fc := fib(30)

    fmt.Println("The first 3 Fibonacci numbers:", <-fc, <-fc, <-fc)
    fmt.Println("The next  3 Fibonacci numbers:", <-fc, <-fc, <-fc)
    fmt.Println("The next  3 Fibonacci numbers:", <-fc, <-fc, <-fc)
    fmt.Println("The next 12 Fibonacci numbers:")
    for k := 0; k < 12; k++ {
        fmt.Printf("%d ", <-fc)
    }
    fmt.Println()

    // as the demand exceeds the 30 numbers a zero value is shown
    fmt.Println("The next 12 Fibonacci numbers:")
    for k := 0; k < 12; k++ {
        fmt.Printf("%d ", <-fc)
    }
    fmt.Println()

    // trap the possible end of supply this way
    fmt.Println("The next 12 Fibonacci numbers:")
    for k := 0; k < 12; k++ {
        val, status := <-fc
        if status == false {
            fmt.Println("channel empty")
            break
        }
        fmt.Printf("%d ", val)
    }
}

/*
A Fibonacci generator via channel/goroutine:
The first 3 Fibonacci numbers: 0 1 1
The next  3 Fibonacci numbers: 2 3 5
The next  3 Fibonacci numbers: 8 13 21
The next 12 Fibonacci numbers:
34 55 89 144 233 377 610 987 1597 2584 4181 6765
The next 12 Fibonacci numbers:
10946 17711 28657 46368 75025 121393 196418 317811 514229 0 0 0
The next 12 Fibonacci numbers:
channel empty
*/

Edited by vegaseat

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.