Arrays & Slices

Slice pre-allocation

Array from a slice

Structs

Copying structs (shallow)

You can create a de-referenced copy of a struct:

package main

import "fmt"

type MyStruct struct {
	ID int
}

func main() {
	myStruct := &MyStruct{ID: 1}

	var myStruct2 = new(MyStruct)
	myStruct2 = myStruct
	*myStruct2 = *myStruct // de-referenced shallow copy
	myStruct2.ID = 2       // doesn't modify myStruct
	fmt.Printf("%p %v\\n", myStruct, myStruct)
	fmt.Printf("%p %v\\n", myStruct2, myStruct2)

	var myStruct3 = new(MyStruct)
	myStruct3 = myStruct
	myStruct3.ID = 3 // modifies myStruct
	fmt.Printf("%p %v\\n", myStruct, myStruct)
	fmt.Printf("%p %v\\n", myStruct3, myStruct3)

	myStruct4Value := MyStruct{ID: 4}
	myStruct5 := &myStruct4Value
	myStruct5.ID = 5 // modifies myStruct4Value
	fmt.Printf("%p %v\\n", &myStruct4Value, myStruct4Value)
	fmt.Printf("%p %v\\n", myStruct5, myStruct5)
}

Source: https://stackoverflow.com/a/21011115/9022642

Copying structs (deep)

Cannot be done in base Go.

Requires custom function or external libraries. e.g. https://github.com/barkimedes/go-deepcopy, https://github.com/qdm12/reprint

Advanced struct ↔️ JSON handling in Go

Marshal/Unmarshal vs Encode/Decode

https://dev.to/jpoly1219/to-unmarshal-or-to-decode-json-processing-in-go-explained-5870

In general, Encode/Decode takes less memory, but other than that use whichever is easiest for the data type you’re working with

Singleton

Modified version from source

package singleton

import (
	"fmt"
	"os"
	"sync"
)

type single struct{
	myAPIKey: string
}

var (
	instance *single
	once     sync.Once
)

// Returns the singleton instance.
func GetInstance() (*single, error) {
	var err error
	once.Do(func() {
		apiKey, ok := os.LookupEnv("MY_API_KEY")
		if !ok || len(apiKey) == 0 {
			err = fmt.Errorf("missing my API key")
			return
		}

		instance = single(apiKey)
	})

	if instance == nil || err != nil {
		return nil, fmt.Errorf("cannot instantiate singleton: %w", err)
	}

	return instance, nil
}

func DestroyInstance() {
	instance = nil
	once = sync.Once{}
}

Imports

Dot imports

package main

import (
  "fmt"
  . "math" // All of math's exported members now directly available
)

func main() {
  fmt.Println(Pi) // 3.141592653589793
  fmt.Println(Sin(Pi / 2)) // 1
}

Errors

Joining errors

// Go 1.20+
var (
  err1 = errors.New("Error 1st")
  err2 = errors.New("Error 2nd")
)

func main() {
  err := err1
  err = errors.Join(err, err2)

  fmt.Println(errors.Is(err, err1)) // true
  fmt.Println(errors.Is(err, err2)) // true
}

Memory allocation