IEnumerables transferred to Golang
Tags: csharp, go
Published: 2020-12-02 18:02:15

There is no doubt that the `IEnumerable` type from C# is very powerful.
It's especially effective when the data we would like to iterate has yet to be aquired or calculated.

To state a matching example, the fibonacci sequence is one of them.
There we have a sequence with numbers depending on the numbers beforehand. So the next number is the sum of the two previous ones. I guess everyone is familiar with this sequence - here it is for numbers up to 100:
```text
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
```

When calculating this sequence  and storing it using an `Array` datatype, we would have to generate these numbers and allocate memory.
Furthermore, we would have to figure out how many fibonacci numbers we would like to generate beforehand, 
because the fibonacci sequence is basically infinite, but our `Array` is not.

Of course, one could do this without allocating a new `Array`, but then you have to implement the generation code in the same method.

```csharp
static void Main(string[] args)
{
	// a loop for printing the numbers
	foreach (var x in GetNumbersArray(12))
	{
		if (x > 100)
			break;
		Console.WriteLine(x);
	}
}

static int[] GetNumbersArray(int i)
{
	int[] result = new int[i];
	
	var (a, b) = (0, 1);

	// and another loop for generating the numbers
	for (var counter = 1; counter < i; counter++)
	{
		// logic without allocating a new array
        // would have to be implemented here
		(a, b) = (a + b, a);
		result[counter] = a;
	}

	return result;
}
```

Here the C# `IEnumerable` type helps out. It combines the best of the two worlds. No extra memory has to be allocated and the computation runs as we request the next item. In addition, no loops takes place more than once (as it is the case with the `Array`).


So the solution using the `IEnumerable` would look like this:

```csharp
static void Main(string[] args)
{
	// request the next number by iterating
	foreach (var x in GetNumbers())
	{
		// break the loop when we reach more than 100
		if (x > 100)
			break;
		Console.WriteLine(x);
	}
}


static IEnumerable<int> GetNumbers()
{
	var (a, b) = (0, 1);

	while (true)
	{
		(a, b) = (a + b, a);
		// return the next number as soon as requested
        // using the yield statement
		yield return a;
	}
}
```

No memory gets allocated to store the sequence, and the caller of the `GetNumbers()` could decide when to break the loop.


## Translating to go
In Go we do not have something like the `IEnumerable` in C#, in fact we have no chance to create a custom type that allows us to be iterated by implementing an interface. In C# we could achieve this by using the `IEnumerator` interface. Of course we do not have to reinvent the wheel, everything we have to do is rebuild the interface from scratch using custom types and access methods.


```go
type Fibonacci struct {
	a int
	b int
}

// Get return the current value to print
func (f *Fibonacci) Get() int {
	return f.a
}

// Next calculates the next value
// and returns false if there are no more values
func (f *Fibonacci) Next() bool {
	f.a, f.b = f.a+f.b, f.a
	return true
}

// NewFibonacci initializes a new Fibonacci type
func NewFibonacci() Fibonacci {
	return Fibonacci{
		a: 0,
		b: 1,
	}
}

func main() {
	sequence := NewFibonacci()

	for sequence.Next() {
		if x := sequence.Get(); x < 100 {
			fmt.Println(x)
		} else {
			break
		}
	}

}
```


This is now the same way as C# `IEnumerator` is implemented under the hood. We are able to iterate using the `Next()` method and access the current value using the `Get()`method. It perfectly fits our needs and satisfies our requirements. No additional memory has to be allocated and no loop is executed twice. Using this blueprint, every usecase for `IEnumerable` can be solved in Go. In fact, it is already in use in Go's standard library. 

> One example implementation would be the `bufio.Scanner` type - https://pkg.go.dev/bufio#Scanner