Fibonacci implementation in Go At the end of the Day 1 Go Course slides (pdf) there is an exercise stated as follows (NOTE: the course in the linked presentation is considered obsolete. If you are looking to learn Go the suggested route is first via http://tour.golang.org):


  You all know what the Fibonacci series is. Write a package to implement it. There should be a function to get the next value. (You don't have structs yet; can you find a way to save state without globals?) But instead of addition, make the operation settable by a function provided by the user. Integers? Floats? Strings? Up to you.


How does the following solution rate with respect to its 'Go'-iness?

package fib

type BinOp func (uint64, uint64) uint64

func fib_intern(a, b uint64, op BinOp) uint64 {
    Fib = func(opnew BinOp) uint64 {
        return fib_intern(b, op(a,b), opnew)
    }
    return a
}

var Fib = func(op BinOp) uint64 {
    return fib_intern(0,1,op)
}


Which can then be called like:

package main

import (
    "./fib"
    "fmt"
)

func add(a, b uint64) uint64 {
    return a+b
}

func main() {
    for i := 0; i &lt; 20; i++ {
        fmt.Println(fib.Fib(add))
    }
}
The link is dead and the code doesn't compile, but there is still an obvious issue to critique:  Part of the challenge was to not save state with "global variables."  In Go, package variables of the package main are typically considered "global variables".  However, only a single instance of any package ever exists at run time, so package variables of all packages are essentially global variables as well.  The code here uses a package variable fib.Fib, thus the code is failing the exercise from the start, working or not.

Edit:  Thank you Anthony for tracking down the archived course and updating the question.  It helps to have the full context.  It also helps to have code working with a current version of Go, which is pretty easy:

package fib

type BinOp func(uint64, uint64) uint64

var Fib func(op BinOp) uint64

func init() {
    Fib = func(op BinOp) uint64 {
        return fib_intern(0, 1, op)
    }
}

func fib_intern(a, b uint64, op BinOp) uint64 {
    Fib = func(opnew BinOp) uint64 {
        return fib_intern(b, op(a, b), opnew)
    }
    return a
}


Go now has stricter checking of static dependencies and reports "initialization loop" with the old code.  My update of your code works by moving the initial assignment of Fib to an init function, which runs at program startup.

I'll abandon this answer now and add another answer where I try to stick to your request for a review of the 'Go'-iness.