Install and update

Two options:

  1. Follow https://go.dev/doc/install, using wget or curl -O to download the file.
  2. or use https://webinstall.dev/golang

Initialize a project

go mod init project_name

Language Features

Arrays

Create and return array inline

return []int{1, 2, 3}
// empty array
return []int{}

Maps

Access a Map. Map access returns value [, exists]

value, ok := myMap["a"]

Check if a value exists

if _, ok := myMap["a"]; ok {
  // Exists
}

Sets

Golang does not have a Set, you can use a map.

s2 := make(map[string]bool)
// or as a literal to insert values at init
s1 := map[string]bool{}

Pointers

Declare a pointer type with * operator

func foo() *string {} // returns a pointer to a string

Use the & operator to get the pointer of a value/struct.

var v int = 100
// we got a pointer to the value of v, also pt1 is of type pointer to int
var pt1 *int = &v

Use the * operator again, to “use” a pointer. When *someVariable is used, we’re modifying the underlying value by reference. If you don’t use the *, you update the pointer itself.

var v int = 100
var pt1 *int = &v
 
// Updating the value using *pt1
*pt1 = 200
fmt.Println("The updated value of variable v is =", v)
 
// Updating the pointer itself
var newV int = 300
pt1 = &newV
fmt.Println("The new value pt1 points to is =", *pt1)

Methods

Golang methods are cool.

Golang is a mostly procedural language, however it adopts certain OOP-like features (as well as FP-like features). Golang Methods are a perfect example.

Take these two functions

type Post struct { ... }
 
func UpdatePost(post *Post) { // Function A
  post.title = "new Title"
}
 
func (post *Post) UpdatePost() { // Function B
  post.title = "new Title"
}

Function A is a function and is called with UpdatePost(post), meanwhile Function B is a method and is called with post.UpdatePost(). Its important to note, that Function B is just syntax sugar. When compiled, both output the same binary.

This is pretty magical IMO. Especially when comparing to javascript, where to achieve the same thing, you’d need to either have a helper inside the post instance or post be a class. Now image you want an array of Posts, in js you’d have to create a new instance of the Post class/object. Meanwhile, in go, no need!

Btw, the post in func (post *Post) UpdatePost(){} is called a receiver argument.

Modules

All files within the same folder must have the same package name. In the main directory where the go.mod file can be found, that package is main. If you want to e.g. make a utils file, with its own package, it needs to be in a folder.

Import and export is done via casing. e.g.

func isNotExported() {}
// vs
func IsExported() {}

Coming from js, where you can do anything (good and bad!), these limitations at first were annoying but I actually quite like them. Every codebase will operate the same and its overall simple.

Though being able to simply grep for export in a file, would have been nice.

Debugging

The equivalent of console.log in go for debugging is the following:

fmt.Printf("%#v\n", levels)
// []list.Item{"Level 0", "Level 1", "Level 2", "Level 3"}

%#v: a Go-syntax representation of the value https://pkg.go.dev/fmt#Printf

Scripting

Abstract

///usr/bin/true; exec /usr/bin/env go run "$0" "$@"
package main
import "fmt"
func main() {
  fmt.Println("Hello, World!")
}

Source

As I learn Golang and find its syntax and standard library really nice, I wondered if I could use it for scripting. Bash scripts get me pretty far, but since I’m a big fan of the Fish Shell, I’d like a shell or even OS agnostic tool. Sure, I could use python. But I don’t like python as much.

Of course, every system has some version of python installed by default, but that’s also true for bash and curl. And if need be, I can just compile and publish some binaries to GitHub.

The above script works splendidly. Its not quite a shebang, but it works the same way.

Templ Developer Experience tips

Tailwind

See Serving Static Files

Add this to your build script.

pnpm tailwindcss -o src/static/styles.css --minify
//tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/**/*.templ"],
  theme: {
    extend: {},
  },
  plugins: [],
}

Vscode Settings

The following will makes templ files get treated as HTML files as far as tailwind/emmet is concerned. This should make templ files have all the conveniences you’d expect and that you’re probably used to when writing JSX.

"tailwindCSS.includeLanguages": {/*...*/"templ": "html"},
"emmet.includeLanguages": {"templ": "html"}, 

Updating

There’s no npm, or volta equivalent for go AFAIK, so you just install from source https://go.dev/doc/install

Remember, you can use wget to easily download the file from the url

Embedding Assets

Sources:

Snippets

Load environment variables

func env(key string, defaultValue string) string {
  value := os.Getenv(key)
  if value == "" {
    return defaultValue
  }
  return value
}
 
// Usage
PORT := env("PORT", "3000")