Eric Workman

Learning Golang, with a demo

Published on

I am learning Go, you know Golang. Why? This site is generated using Hugo, written in Go. I run my projects in Kubernetes which is written in Go. I felt as though it was different enough with these minor touches that it would be worthwhile to learn.

Golang is lower level and definitely has fewer batteries included than most of my day to day languages. It certainly has reminded me how I take for granted what some of the other languages provide. That said, so far, golang has been enjoyable and pretty neat.

So what have I learned?

Arrays vs Slices

As I expected, lists, arrays, maps, and the like iterables work a little differently than in Ruby, Python, and Elixir. Arrays have a type, a capacity, and a length. Slices are views into arrays, and modifications to the underlying array appear as changes the slice. Slices too have a type, a capacity, and a length, but they have bounds as well.

What got me several times:

  • In-place vs returning functions. I'm so used to immutablity with Elixir that I had to readjust to this.
  • Different functions to operate on different types of data. This is a pretty explicit feature with Go.
  • Functions using interface{} for slices. From an new user, this feels like a typing cop-out.
  • I used a lot of func copy(dst, src []Type) int to make new instances of hands so that I didn't accidently modify the original arrays. This was especially true when figuring out what hands a player had and which was strongest.

Dependencies and Packages

This was a radical departure from what I'm used to. I don't mean to misrepresent, but it appears like there is no versioning of packages. Programs use the latest version of any dependencies in the import calls, and it will attempt to find the package that best fits the name. The following snippet will get a dependency when it runs or builds for the first time:

import (
  "github.com/hajimehoshi/ebiten/v2"
)

This is refreshing in a way and sort of terrifying in another. It removes a lot of the hemming and hawing about changing versions and seems to encourage always or near-always backwards compatibility. Like in the example, it also encourages major changes as harder package forks from a project than an in place change. It is also terrifying as I have no control over the dependency if I do run into a problem with something. I can see this being a smaller issue in a language that pushes compatibility than with what I've experienced in Ruby and Python.

Building and Installing

Compile times are fast. The compilation is pretty helpful with errors. I so far do not like that it errors when variables are unused, but I do understand why that might be a worthwhile stand to take. It puts out a simple binary, and I have no real comment about the size or complexity of this. That binary can just be executed on the targets. Simple.

Installing is pretty simple with go install or moving a compiled binary.

Ebiten and WebAssembly

I've tried my hand with game frameworks before in languages like Lua (LÖVE). Ebiten is a fairly simple 2d engine. My experience is not very broad here, but it was really dead simple to get a game going. It compiled and worked just like a regular program, but it also cross-compiled to WebAssembly. I made 0-changes to my simple "game," and it just worked. Isn't that just really neat?

Demo

Here's the WebAssembly output of an Ebiten project meant to partially simulate a poker hand. There's no betting or raising, so it is suitable to see how hands play out and what sort of chances your hand has at being the strongest. It is certainly imperfect, e.g. you might see an Ace-low straight beating a 6-high straight. There's a lot for me to do. I'm still improving and tweaking it, and I'll update the version here as I go. I'll eventually open the code up on GitLab too.

This works best on a desktop browser and not a mobile device.

Controls:

  • space to do the next draw action
  • q to reset the table and players
  • r to reveal all hands at any point

Enjoy!