Latest sites

Quick news

  • 2014-03-27: MongoDB Watchdog module ported to Drupal 8 at the Szeged Dev Days.
  • 2014-01-26: My post on the Symfony web profiler in Silex selected in Week of Symfony. w00t !
  • 2013-10-18: My first commit went into MongoDB today. And, guess what ? It's in JavaScript
  • 2013-09-20 to 29: Working on Drupal 8 EntityAPI at the extended code sprints during and around DrupalCon Prague
  • 2012-08-19: Working on Drupal 8 EntityAPI at Drupalcon Munich
  • 2012-06-15: Working on Drupal 8 EntityAPI at DrupalDevDays Barcelona
  • 2012-03-23: Working on the future Drupal Document Oriented Storage at DrupalCon Denver. D8 or later ? Bets are on Later

Golang fun : adding methods to primitive types

Go syntax has some funny peculiarities which are not immediately obvious, like methods on primitive types. Let's have a look.

Primitive wrapper types

Anyone with a few hours of Go is familiar with the basic object notation, like this example:

package main

import "fmt"

type Int struct {
  value int
}

// Imagine this is an actually complex and useful function instead.
func (i Int) Add(j Int) Int {
  return Int{i.value + j.value}
}

func main() {
  i := Int{5}
  j := Int{6}
  fmt.Println(i.Add(j))
}

Try it on http://play.golang.org/p/GUgWEz_nXd

Looking for simplicity

The problem, of course, is that not only is this useless, it is also ugly, because we are wrapping a primitive type in a useless struct. What we probably would like would be something like this, like one can do in Ruby, where all types are objects which can receive methods:

package main

func (i int) Add(j int) int {
  return i + j
}

func main() {}

But if we try this, the Go compiler complains, as you can see on http://play.golang.org/p/95YSh_rmBo

prog.go:3: cannot define new methods on non-local type int

A solution

Now, Go has the ability to assign types to other types:

type Int int

Unlike in some languages where types are first-class objects, this is not aliasing: the two types will be different when compared, but offer the same capabilities. And this brings us the expected capability:

package main

import "fmt"

type Int int

func (i Int) Add(j Int) Int {
  return i + j
}

func main() {
  i := Int(5)
  j := Int(6)
  fmt.Println(i.Add(j))
  fmt.Println(i.Add(j) + 12)
}

Run it on http://play.golang.org/p/Y49wr_gYPo

There we have it : we added a method on a type which is a copy of a primitive type. No struct boxing, no unboxing in the method.

Why it matters

The real beauty of this is actually not the ability to attach the method, although this is definitely satisfying from a conceptual point of view, bringing consistency with an approach opposite to that or Ruby, it is rather the code in the Add() method itself, and the last line in main() are actually the beauty of the thing : since our local Int type is actually just a name for the intrinsic int, it still support the builtin operators like naked ints: no explicit casts needed to use the aliased variable in an expression.

Is it possible to define an operator override ?

Is it possible to define a struct method to override "+" itself? To have Int(5) + Int(6) for example?

Operators cannot be overridden

I think I already saw this asked on #golang-nuts more than once : Go1.x does not allow this, and it seems unlikely to appear in 2.x if the current language direction remains stable : see https://golang.org/doc/faq#overloading explicitly rejecting this.