Built-in Go HTTP server

Go has a built-in HTTP server in net/http. Here’s me playing around using it: package main import ( "fmt" "net/http" "strings" ) func hello(w http.ResponseWriter, req *http.Request) { fmt.Fprintf(w, "hello\n") } func details(w http.ResponseWriter, req *http.Request) { resp := []string{} resp = append(resp, "Request Details:") resp = append(resp, fmt.Sprintf("- Request proto: %s", req.Proto)) resp = append(resp, fmt.Sprintf("- Headers:")) for name, val := range req.Header { resp = append(resp, fmt.Sprintf("\t- %s: %s", name, val)) } resp = append(resp, "\n") fmt....

2022-10-14

Fixing: File is not `goimports`-ed (goimports)

The other day, I was linting my Go code with golangci-lint when I got this error: File is not `goimports`-ed (goimports) I examined the file and found nothing amiss, but the linter insisted something was wrong. Eventually, I realized I had used spaces to indent the file rather than tabs. Changing the indent character to tabs fixed it. I then ran into the same error on a second file. This time, I had a comment which was wrong....

2022-10-05

Go and pass by value

Go normally uses pass-by-value for function calls. When you pass a variable into a function or method, Go will (under the hood) create a new variable, copy the old variable’s value into it, and then pass the new variable (not the original variable) into the function or method. Non-pointer values These types behave as described above and are sometimes called non-pointer values: Strings Ints Floats Booleans Arrays Structs Here’s an example of how these work....

2022-09-01

Constants in Go

Constants syntax I always have a hard time remembering the syntax of declaring constants in Go. So here’s some reminders to myself. It is possible to declare constants one per line like you’d expect. Note that the there are typed and untyped constants as shown here below. package main import "fmt" const vermKnid string = "scram" const fox = "foxes likes loxes" func main() { fmt.Println(vermKnid) fmt.Println(fox) } But you can also use a constant declaration group, which does the same thing but is easier to read if you’re declaring a bunch of constants....

2022-08-16

Mutexes and concurrent access in Go

Golang has mutexes (short for mutually exclusion) to manage concurrent access to a shared object via multiple goroutines. Here’s an example (taken from the excellent Go by Example: Mutexes). package main import ( "fmt" "sync" ) type Counter struct { mu sync.Mutex count map[string]int } func (c *Counter) Inc(name string) { c.mu.Lock() defer c.mu.Unlock() c.count[name]++ } func main() { cnt := Counter{count: map[string]int{"james": 0, "spartacus": 0}} var wg sync.WaitGroup increment := func(name string, n int) { for i := 0 ; i < n ; i++ { cnt....

2022-07-22

Go routines and WaitGroups

Working with Goroutines is simple. You simply pre-prend your function call with go and you’re off and running. Here’s an example which calls the expensive() function five times before exiting. package main import ( "fmt" "time" ) func expensive(id int) { fmt.Printf("Worker %d starting\n", id) time.Sleep(time.Second) // Oh, so expensive! fmt.Printf("Worker %d ending\n", id) } func main() { for i := 0; i < 5; i++ { go expensive(i) } fmt....

2022-07-18

Closures in Go

In Go, it’s pretty easy to write an anonymous function. package main import "fmt" func main() { func(s string){ fmt.Println("s is:", s) }("hello world") } Running the above code produces: $ go run main.go s is: hello world You can even assign the anonymous function to a variable like so: package main import "fmt" func main() { myFunc := func(s string){ fmt.Println("s is:", s) } myFunc("hello again, world!") } Now we get this output from the above code:...

2022-07-13

Generics in Go 1.18

In Go 1.18, we get access to Genrics. Huzzah! Here’s an basic example of how to use them: package main import ( "fmt" ) func PrintAge[age float32 | int64](myAge age) { fmt.Printf("age: %s \t type: %T\n", myAge, myAge) } func main() { var age1 float32 = 30.5 var age2 int64 = 32 PrintAge(age1) PrintAge(age2) } Running the above program gives us the below output. You can see that it happily accepted the float32 and int64 values without issue....

2022-07-12

Go defer

defer in go is used to run a function later on. Specifically, the specified function will run when the enclosing function returns. There’s no clean equivalent to this in Python that I’ve found. The quintessential example is closing a file handle as your program exits. Example package main import ( "fmt" "os" ) func main() { file := createFile("/tmp/testingdefer.txt") defer closeFile(file) writeFile(file) } func createFile(path string) (file *os.File) { fmt.Println("creating file: ", path) file, _ = os....

2021-07-20

Empty Go Interfaces

When declaring function parameters in Go, you must type the incoming data. Here’s an example: package main import "fmt" func print_stuff(s string) { fmt.Println(s) } func main() { print_stuff("Passing string!") } s string indicates that we’re passing a variable of type string into the function. This prevents us from from passing into variables of any other type. For example, this will fail with ./prog.go:10:17: cannot use 42 (type untyped int) as type string in argument to example_str if you try to pass an integer....

2021-07-11