Cross concerns such as logging, instrumentation and authorization are like bad contractors. One needs them, but they tend to leave a mess. A cross concern violates the single responsibility principles which states that a class or a module should have one and only one reason to change. Violating this principle results in code that is difficult to understand with intertwined rules. The core business of the application gets buried under tons of unrelated code, which extends to tests as well. A test case will either test multiple unrelated concerns or duplicated for each concern.
In the unbuffered channels post final example
countUp(counts chan int)will always send values to the channel while
printOutput(counts chan int)will always receive values from the channel. We can make that explicit in the type of the channel. The
countUpargument will be
counts chan <- intto signal a channel that only receives values. and the
printOutargument will be
counts <- chan intto signal a channel that only produces value. Feel free to check the final implementation on Go Playground.
Channels are Go’s mechanism for communication between goroutines(think lightweight parallel threads). One can send a message from one goroutine to the other.
We can think of a goroutine, as a lightweight thread. When a new program starts by calling
mainit starts in a goroutine, conveniently called the main goroutine. We can invoke a function in a new goroutine by prefixing the function call by the keyword
There is no inheritance in Go, but there are interfaces! Interfaces has methods and any type having the same methods satisfies that interface. In that sense, that type is an instance of that interface. So, in Go, you will not find
with. It just happens. In my personal opinion, you lose a bit of type self-documentation. Thus, there is no override either. So, unless I discover something interesting, you might rename a method and no longer satisfy an interface that the type used to.
Functions in Go are first class citizens. Function may return one or more arguments. They may take a function as an argument. We cover these topics here. We take a look at variadic functions in Go, which are functions that take zero or more arguments. A deferred function is a function that is executed at the end of the execution of its enclosing function.
Pimp my Library is a term coined by Martin Odersky explaining how Scala gives you the option of enriching types that you might not own. It comes to mined when you think about how methods can only have receivers in the same package. It turns out it is possible to create methods for receivers you don’t own and hence extend existing types or other libraries. There are other advantages of this of course. Let’s have a look at enriching int. We will just add a method
int. This is redundant of course to
++but it is a simple example in one hand, and it is immutable on the other.
Let’s create a simple type,
accountwhich has one field
money, we will create a one method
addwhich will add some money to the account.
Go Functions may have multiple return values, by convention the last result is an error indicator or an error. An error indicator is a boolean that will evaluate to true if there is no errors.
Go collections is very easy to learn. We have arrays and its close cousin slices. Then there are maps and that’s it. You can form a set using map keys as values. We will see how to create each of these types. How can we iterate through each of those types. We will see how to add an element to an existing collection.
Go has a different way compared to languages such as Java, Scala and C in handling commandline arguments and flags. There are built in utility to generate commandline help message and assign default values to flags. One can create flags that maps to more complex data types.
typeis not a type alias, which is different than Scala for an example. The new type is not compatible, assignable or comparable to the original type. In my mind this is better than type aliasing because type aliasing, if overused, is in many cases redundant and confusing.
type timeInSeconds intand
type timeInMilliSeconds intare not compatible. You need to cast from one to the other (or just for correctness to
intand then to the other) to convert.