loading...
Cover image for About Go

About Go

cacilhas profile image Arĥimedeς ℳontegasppα ℭacilhας Updated on ・3 min read

Text from Kodumaro.

Gopher

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
}
Enter fullscreen mode Exit fullscreen mode

If one has defined a struct:

type personType struct {
  firstName, lastName string
  birth               time.Time
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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

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

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)
      }
    })
  })
}
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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
  ...
}
Enter fullscreen mode Exit fullscreen mode

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.
  ...
}
Enter fullscreen mode Exit fullscreen mode

Afterword

Some useful resources:

Discussion

pic
Editor guide