About Go

2020-10-31
The shadows behind the code.

Gopher

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

Outflanking

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).

Interfaces

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.
  ...
}

Afterword

Some useful resources:


Also in DEV.to.