Variables

AI-generated

// Declare, then assign.
var someInt int
someInt = 42

// Short declaration with type inference. This form is valid inside functions.
someOtherInt := 42

// Grouped declarations are valid at package or function scope.
var (
    SomeIntPublic = 42 // Exported because the name starts with an uppercase letter.
    privateText   = "visible only inside this package"
)

caps := map[string]string{
    "a": "A",
    "b": "B",
    "c": "C",
}

If-Else

if condition {
    //
} else {
    //
}

Loops

for i := 0; i < 42; i++ {
    //
}

// Infinite loop, similar to `while(true)`
for {
    //
}

// Similar to `while(i < 10)`
i := 0
for i < 10 {
    //
    i++
}

// Looping over lists/arrays/slices
someList := []string{ "Apple", "Banana", "Carrot" }
for index, element := range someList {
  fmt.Printf("At %v -> %v\n", index, element)
}

// Looping over maps
someMap := map[string]string{
  "a" : "A",
  "b" : "B",
  "c" : "C",
}
for key, val := range someMap {
  fmt.Printf("For key: %v, value is: %v\n", key, val)
}

Functions

// returning function
func PublicSum(a int, b int) int {
  return a + b
}

// void function
func PrintHello() {
  fmt.Print("Hello")
}

// not visible outside current package
func privateSum(a int, b int) int {
  return a + b
}

Structs and Objects

type Person struct {
  Name  string
  Age   int
}

// usage
person := Person{
  Name: "John",
  Age:  42,
}

Methods and Receivers

type Person struct {
  Name string
  Age int
}

// this 'p' is called a receiver
func (p *Person) PrintName() {
  fmt.Print(p.Name)
}

func (p *Person) DoubleTheAge() int {
  return p.Age * 2
}

Passing By Reference and By Value

type Light struct {
  Color string
}

func ChangeLightColorByVal(light Light, newColor string) {
  light.Color = newColor
}


func ChangeLightColorByRef(light *Light, newColor string) {
  light.Color = newColor
}

func main() {
  light := Light{Color: "green"}
  ChangeLightColorByVal(light, "red")
  fmt.Println(light.Color)

  ChangeLightColorByRef(&light, "red")
  fmt.Println(light.Color)
}

Interfaces

AI-generated

Interfaces describe behavior. A concrete type implements an interface implicitly by providing its methods; there is no implements declaration.

Keep interfaces small and define them near the code that consumes them. The empty interface any accepts a value of any type, but using it gives up compile-time knowledge and should not be a default abstraction.

Type assertions

AI-generated

value, ok := input.(string)
if !ok {
    return fmt.Errorf("expected string, got %T", input)
}

Use the two-result form when a different dynamic type is expected; a failed single-result assertion panics.

Type switches

AI-generated

switch value := input.(type) {
case string:
    fmt.Println("string:", value)
case int:
    fmt.Println("int:", value)
default:
    fmt.Printf("unsupported: %T\n", value)
}

Compile-time contract check

AI-generated

var _ Animal = Dog{}

The blank identifier turns an accidental missing method into a compile-time error.

Composing interfaces

AI-generated

type ReaderWriter interface {
    io.Reader
    io.Writer
}

Implicit implementation

AI-generated

type Animal interface {
  Speak() string
  Legs() int
}

// Any struct implementing/having an interface's all the methods
// it automatically implements that interface
type Dog struct{}

func (d Dog) Speak() string {
  return "Bark"
}

func (d Dog) Legs() int {
  return 4
}

var animal Animal
animal = Dog{}
fmt.Print(animal.Speak())