< up
2024-06-19

GopherCon Europe 2024

I attended the GopherCon Europe 2024 in Berlin1 to check out the latest GOssip2.

Some data:

Contents

  1. The Business of Go
  2. Rethinking domain-driven design
  3. Go Team Panel
  4. GoTime Podcast
  5. HTTP Routing
  6. Recommendations
  7. Impressions

The business of Go

The Go Product Lead from Google Cameron Balahan gave some insights into googles perspective and motivations about go.

Rethinking domain-driven design

The principal engineer Robert Laszczak from /ID talked about Domain-Driven Design (short: DDD).

Introduction

DDD is about encapsulating business logic into separate coherent/independent components instead of having one chunk of logic. The motivation is to avoid accidental complexity that comes with entangling multiple domains with another. There are manifold ways of implementing this concept after identifying several domains within a codebase that could be separated. Usually they all have in common that the external interface is generic enough that the internals can be swapped easily. Wherever those components are implemented within different micro services or go structs that encapsulate the inner logic in private.

This reminds me of the basics of Object Oriented Programming (short OOP), where data and code is encapsulated within a class. The external interface provides an abstraction and ideally the caller doesn’t need to know how the class-specific problem is solved.

Robert also stated that DDD is not the ultimate solution for everything. Especially for small code bases it’s usually overhead and lead to overengineering.

Idea 1 - always keep valid state in memory

Use private struct fields and public methods to control the access and especially modification of the inner state to ensure the inner state is always valid.

E.g. a struct Person providing an age, should ensure its not negative. This can be accomplished by only setting the age within the constructor func NewPerson(name string, age int) (Person, error) with a validation beforehand. If the validation fails, the constructor fails (age < 0) with an error.

type struct Person {
  name string
  age  int
}

func NewPerson(name string, age int) (Person, error) {
  if age < 0 {
    return Person{}, errors.New("age must >=0")
  }

  return Person{
    name: name,
    age: age,
  }
}

Getters do also have another usage than just provide access to private variables. They can calculate values on the fly that would be otherwise likely to get outdated.

E.g. in order to have the correct age of an user, at any time, it would be easier to store the year of birth than the age. A getter func (p Person) Age() int then gets the current year and calculates the age on-demand, instead of storing it within the struct, doomed to get outdated3:

type struct Person {
  name        string
  yearOfBirth int
}

func (p Person) Age() int{
  return time.Now().Year() - p.yearOfBirth
}

Idea 2 - keep domain-logic database-agnostic

Well, the title says it all. Business logic and storage layer should be abstract enough to be interchangeable. This prevents salami-code where domain- and storagecode is entangled into another.

Go’s Interfaces are a perfect fit for this, defining an external set of functions that some type needs to satisfy.

E.g. a simple CRUD storage backend of a person could look like this:

interface Storage {
  Get(name string) (Person, error)
  Add(p Person) error
  Update(name string, age int
}

In order to get an prototype fast, the first backend could be implemented using a file. As data grows this backend could be replaced with a sqlite db. You discovered that a key-value db fits better and implement a redis/valkey backend. Whatever storage backend is used, the layer above using a backend via the storage interface can stay the same throughout the storage journey.

Idea 3 - Reflect your business logic internally literally

Interesting take about simplifying requirements engineering and requirement validation with non-technical stakeholder or user of the application. Write the struct field and types as close to the formular feature definition as possible. Non-technical people might find this easier to read as.

For example: A person should have a firstname and lastname such as a year-of-birth. It can also have documents attached, if any.

struct {
firstname string
lastname string

yearOfBirth int

documents []Document
}

Go Team Panel

Four members of the Go Team answered questions from the crowd:

Questions:

GoTime Podcast

An episode of the GoTime Podcast with GopherCon moderator and podcast host Mat Ryer got recorded at the end of the first day. Some speakers played against each other ranking the answers of a local go survey. It was

HTTP Routing enhancements

Go Team member Jonathan Amsterdam talked about the recent pattern routing feature in the standard lib net/http and its challenges. To this feature, route matcher could only be literal without any variables or wildcards in it.

Recommendations

Talking with people at conferences always results in a list of recommendations. Some are reasonable, other might be random:

Impressions

Me starting $this blog post using my notes.

Huge LCD screen at track 1.

The European Championship 2024 took place in parallel of the GopherCon. Luckily they decided to stream the game “Germany - Hungary” onto the largest screen I ever saw \o/

Got myself a fluffy gopher and some stickers.


  1. as part of the Hetzner Cloud Instance Team.
  2. shameless pun intended :D
  3. Caching-wise, it would also make sense to cache such values that don’t often change e.g. to accelerate requests.