About Go

The shadows behind the code.


Now I’m revisiting an old post of mine about my personal impressions about the Go language.


My first impression on Go was very wrong. I flanked Go from the Python and Node.js perspective, which was very disappointing. When you try to use a language that offers powerful tools to access system resources with an open-and-shut mind, the result is frustrating.

As soon as I understood Go is closer to C++ and Objective-C, I realised it’s a cool, powerful, and fun programming language.

At that time, a friend vainly tried to explain me Go pointers as read-write parameters against read-only ones. If he had simply told me “pointers like in C,” I’d get at once.

My disapproval to Go is that Alphabet might not have recreated the wheel so hard, it could take advantage of other well-tested platforms, like Vala and C♯ did. It would entice lotta god programmers by the soft learning curve (despite Linus Tovarlds disagrees).


In Go, interfaces look like structural types in Scala.

In other hand, structs are much like Objective-C @interfaces.

An instance of any struct that matches an interface is instance of the inteface too, just like structural types.

For sample, take the following interface:

type Person interface {
  FirstName() string
  LastName() string
  FullName() string
  Birth() time.Time

If one has defined a struct:

type personType struct {
  firstName, lastName string
  birth               time.Time

And then every function from Person is implemented for personType:

func (p personType) FirstName() string {
  return p.firstName

func (p personType) LastName() string {
  return p.lastName

func (p personType) FullName() string {
  return strings.Trim(fmt.Sprintf("%v %v", p.firstName, p.lastName), " ")

func (p personType) Birth() time.Time {
  return p.birth

Then it’s possible to return a personType as Person:

func NewPerson(firstName, lastName string, birth time.Time) Person {
  return personType{firstName, lastName, birth}

Unit tests

For testing, Go’s got a built-in testing library, that’s very easy to use.

Being very verbose, a yet simple example may be:

func TestPerson(t *testing.T) {
  timeForm := "2006-01-02"
  birth, _ := time.Parse(timeForm, "2017-06-12")
  p := NewPerson("John", "Doe", birth)

  t.Run("primary methods", func(t *testing.T) {
    t.Run("FirstName", func(t *test.T) {
      if got := p.FirstName(); got != "John" {
        t.Fatalf("expected John, got %v", got)

    t.Run("LastName", func(t *test.T) {
      if got := p.LastName(); got != "Doe" {
        t.Fatalf("expected Doe, got %v", got)

    t.Run("Birth", func(t *test.T) {
      expected, _ := time.Parse(timeForm, "2017-02-12")
      if got := p.Birth(); got != expected {
        t.Fatalf("expected %v, got %v", expected, got)

  t.Run("secondary methods", func(t *test.T) {
    t.Run("FullName", func(t *test.T) {
      if got := p.FullName(); got != "John Doe" {
        t.Fatalf("expected John Doe, got %v", got)

Enough for most cases.

In order to understand Go time format: Format a time or date.

Catching exceptions

The Go’s exception catching pattern is returning the error as second argument for every function that can go wrong.

In the sample above, one can found this line:

birth, _ := time.Parse(timeForm, "2017-06-12")

The underscore (_) means the exception is discarded. If one wanna deal with the exception, one can do something like:

birth, err := time.Parse(timeForm, "2017-06-12")
if err != nil {
  // Deal with the exception

Another way Go can throw an exception is by a panic attack. One can do it by calling the panic() function.

The only way to catch this kind of exception is calling recover() inside a defer block.

One can catch the exception and return it through a writable channel (chan or chan<-).

It smells like:

func DoSomethingDangerous(res chan<- error) {
  defer res <- recover()

  // Do somenthing that can raise a panic attack.


Some useful resources:

Also in DEV Community 👩‍💻👨‍💻.