Inspection, on the go
Tags: go, programming
Published: 2023-08-03 11:01:26

Hello everyone.
I just learnt the go language, and I want to share my experience of using it.
At first, golang was just an "Oh, just another programming language" for me, but as I go throw, I found noticeable points about that.
I am also a functional programming enthusiast and I'll compare go with FP rules and methods.

## Syntax
It's syntax is c-like, and borrowed some features from python, like range, for and if without parentheses, being free of semicolons, and more.

### :=
It's a good simplifier. No more writing type for values. It's like var in java or C#.

## Core Library
Like python, go has a rich core library with many useful stuff in it. One of them I worked with is `database/sql`. It provides good interface for implementing libraries that work with dbs.

## Interface
Interfaces are a big point of difference. They are really good, that C lacks them. They provide us significant "polymorphism", without needing OOP's inheritance, that one state at 10th parent may change, and causes your program explode and you don't know why!

### Some words of polymorphism:
Polymorphism means you can we can share on behaviour between different types. A great pure FP language like Haskell also has it, with the name of 'type-class'.
Inheritance also provides polymorphism, but inheritance also causes great unpredictability to our apps, and that's also because it breaks apart our app's state and spreads them in different places of our app. But with interfaces, it just shares behaviours between types, and leaves the state in our hands.

## Error Handling
Error Handling in go is interesting. Errors (or in another term, "Exceptions") are just values and will be handled like values, in contrast with another languages that handles errors with syntax.
But there is a problem with the bunch of `if err != nil` parts in code. If there was syntaxic sugar for that, it will be far far better for code to be clean and readable. Maybe something like this:
``` go
// when you see err:
// panic
ra, (err; panic) := res.RowsAffected()
// run a func, e.g. handle
ra, (err;handle()) := res.RowsAffected()
// return something
ra, (err;return whatToDoWith(err)) := res.RowsAffected()
```
Go has another type of errors too. In some rare cases that you don't know what to do with an error and it's totally unexpected, you just need to `panic`, and if you found a way, you can `recover`.

## Goroutines and Channels
Goroutines are one of the top points in go, maybe the apex point. They really simplify concurrency, but in my opinion, not more simplifier than async programming.
They are like threads in java, and somehow like async-await and coroutines (in C#, python, js, ...), because you must wait for a channel to send something so you receive it and continue.
Goroutines are also a way of having streams. For example, in a http server, you will receive the requests, send them to a goroutine via channel with a handler, that goroutine processes them and will send response. Also we can have some middlewares. 

## Generics
Generics are advanced but crucial feature that I think, every modern language must have, as many languages have. Go added this feature in 1.18. Go Generics have two usage, Generics like other language, and most wanted UNIONS. Unions are very useful, they make many values typed that couldn't be typed before. For example, a function takes a parameter that can be string or integer. Before generics, we should mention `interface {}` for that parameter, then check if its type is integer or string, and if it isn't, make error.
```go
func testFun(a interface{}) error{
	switch a.(type) {
	case string, int:
		// do sth ...
	default:
		return errors.New("not integer nor string")
	}
	return nil
}
```
But now, with generics:
```go
func testFun2[T string|int](a T) {
	// do sth ...
}
```
Generics also leverage type inference for inferring type of value and omitting type arguments. As a simple example:
```go
s := "hello"
// without inference
testFun2[string](s)
// with inference
testFun2(s)
```
This is a simple example but type inference has more complicated aspects. You can read more about them and also other things about generics in go, in this article: [An Introduction To Generics](https://go.dev/blog/intro-generics).
Also mention that type inference is the characteristic of FP languages, and now we see it in many other languages like Go, C++, C#, Java, … .

## What about FP in go
Go is not a specifically FP language, but you can obey FP rules in your own. You can do not changing variables, you can use recursive functions instead of loops and you can have pure functions.

Thanks to generics, you can have some abstractions like Maybe, Either, ... , that exists in some FP languages, and this is really a good point. I saw a lib that implemented some of them that you can use them: [github.com/samber/mo](https://github.com/samber/mo).

But something extremely lacks. Three loopy function, map-filter-fold aren't part of language itself but they very needed. You can use libraries for having them (like one mentioned above), but I think we need them in core language because of their usefulness.

There are something like if-else _expressoin_, switch _expression_, pattern matching, ... for completing the full taste of functional programming in go, that I hope to see them in an early future.

## Last Words
Go is a good simple nifty language. I like to use it more. Also I like to learn its rival, rust lang.

Thanks for reading my article. Please comment me if you have opinions or critics about my article.

Goodbye!