Introduction

Go is a language where concurrency is first class citizen, it can be used to concurrently run applications using the language native constructs with ease, and efficiently.

Although Go compiles to native binary, it still has two main components attached to it, a scheduler, and a garbage collector.

Garbage collection in Golang, is meant to run frequently with small puases, rather than big but less frequent pauses.

Scheduler is the component responsible what enables concurrency constructs to run smoothly, it manages OS thread pool and orchestrates goroutines.

Values & Types

Go supports the following types

int8, int16, int32, int64, int, uint8, uint16, uint32, uint64, string, rune, byte, bool, float32, float64, byte

int is an alias for either int64 or int32 depending on system architecture, i.e 32 bit architectures uses int32 while 64-bit architectures use int64, it should be the default int type to use unless there are limiting factors.

rune is an alias to int32, it represents a unicode character, it provides a semantic meaning to the reader, that this is for dealing with characters rather than numbers

byte is an alias for uint8 again provides a semantic meaning to denote dealing with low level byte data, rather than a number type

float64 is the default floating point number type in Go, and it’s a good default setting to rely on, as float32 can overflow if not careful

Functions

Go treats functions as first class citizens, they can be passed to other functions as an argument, one function can return another function, they can be stored in a variable, and their implementation can change as long as the signature of the function remains the same (by assigning a variable to different impelementations). Signature of the function includes the return type as well.

Go functions can return multiple separate values, it’s not like Python tuple, that eventually single value is returned, it’s genuinely separate values, and while assigning to variables, you need to provide return type many types variables.

In Go, you can specify a name for the return types too, and calling a naked return statement auto-returns the matching names from the return type definition.

You can use the underscore to ignore a value.

Errors are treated as value, and if there is a chance of failure for a function, it should return the error as its last argument. Errors are always the only return type, or always the last one by convention.

Simulating Named Parameters

Go doesn’t support named parameters while passing arguments, nor optional ones but this feature can be simulated by accepting a struct type. When passing a struct every field in the struct is assigned to its zero value by default.

Go Is Call By Value

i.e arguments are passed by value for parameters

It means when you pass arguments to a function, they are copied by default instead of being passed by reference. There are some types implemented with pointers, hence anything passed by pointer changes stick with the passed values.

Every type in Go is a value type. It’s just that sometimes the value is a pointer

Variadic Parameter Types

Variadic parameters must be the last or only element in the parameter definition.

While defining as a parameter, ... is placed in front of the type, and while providing the argument, it’s provided after the argument.

func calcTotal(base int, toAdd ...int) {}

// While calling
calcTotal(1, 2, 3, 4)
// Providing slice and spread args
calcTotal(1, []int{1, 2, 3, 4, 5}...)

Variadic functions underlying data structure is also a slice, hence you can iterate on them, if we were to implement calcTotal function, it would be as follows

func calcTotal(base int, toAdd ...int) {
  total := base

  // Notice how it's allowed to iterate on the variadic parameter
  for _, v := range toAdd {
    total += v
  }

  return total
}

Closures

Closure is a function either received or returned by another function, they close over the scope the function they are defined in