Published on

Getting Going with Go

Authors

On the current project I am on one of the things we need to do is integrate with a Kubernetes infrastructure component. There are clients for this component written in a number of popular languages but using these clients has proven to be quite tricky and finicky.

The component we need to speak to (like most Kubernetes components) is written in Go. As a team we mobbed on this and decided to try write our connector in Go. This proved to be really easy and fast despite the fact that none of us had too much experience with Go.

What really sped this up was we could import the code directly from the desired component's codebase. We did a simple go get -u gitHubUrl/packageName for the exact package we needed from the target component. We then just slapped together a simple class to use this and voilà we had successfully integrated with the Kubernetes component.

What I have found fascinating so far with Go is:

  • No file to keep track of dependencies by default: No package.json, pom.xml, requirements.txt or similar package management file to track changes
    • This was a real shift from other languages. You have to get each dependency you need on each persons machine. But if using the officially recommend dependency manager dep what you do is simply:
      1. go get -u url/package then import and use this in your code.
      2. Go installs this in your local Go repo.
      3. In the absence of a package manager like dep when you use this project on another machine you would need to go get -u all the packages you need
      4. Using dep you can simply dep ensure from the root of a project and it will build up a toml of the dependencies in the project by looking at the imports used in the project.
    • What is interesting and terrifying with this approach is it seems that with the vanilla approach you cannot tell Go to use a fixed/specific version of a dependency.
  • Compile error for unused: the Go compiler actually will not compile/build a file if it has unused imports and variables.
  • Struct methods: instead of extending a class the way you would in an OO language you:
    1. Define a C style struct of the object you want which just has the fields you need.
    2. You then define a method on the fly using a special syntax that indicates what struct you are attaching it to and a name to use to refer to the struct in the method body.
    3. Alternatively if you are in the same package you can use a simpler syntax.
    4. This is similar to Kotlin's extension functions the way you define a method on a class on the fly outside of the class.
  • Very readable code: if you are coming from a language that is C like then Go is very readable.
    • It also has the concepts of pointers like C but it does have a garbage collector (GC). I suspect Go not compiling unused imports and variables helps it optimize the garbage collector.
  • Upper Case vs Lower Case Syntax: In Go if you start a method with an uppercase letter Go exports it (makes the method public). Alternatively if the method starts with a lower case letter then it is only accessible within the class. This same rule applies to field names in structs.
func SomeMethodThatIsPublic(){
  //...
}

func methodThatIsPrivate(){

}

type Person struct{
  Name string, //this field can be accessed off of initialized structs
  surname string //this field can only be accessed in a struct function (see below)
}

func (p Person) getSurname() string {
  return p.surname
}
  • Initialize vs re-assign: := is used to initialize a variable for the first time in Go while = is used to re-assign an already initialized variable:
name := "John"
...
name = "James"

Today was only day one of using Go, but my initial impressions of Go so far are extremely positive. Going from nothing to a very readable and simple client really quickly was a breeze. There is also a large and growing ecosystem of libraries and apps built around Go. I am super eager to delve deeper into the language to see what more it is capable of.