C
h
i
L
L
u
.
.
.
Programming Language

The Complete Go Language Guide

Master Go (Golang) — Google's fast, statically typed, compiled language built for modern software engineering.

Why Learn Go?

Go, also known as Golang, was created at Google in 2007 by Robert Griesemer, Rob Pike, and Ken Thompson. It was designed to address the shortcomings of existing languages in large-scale software development — combining the performance of C with the productivity of a modern dynamic language.

Go excels at building web servers, CLI tools, microservices, cloud infrastructure, and concurrent systems. Its simplicity, fast compilation, built-in concurrency via goroutines, and strong standard library make it one of the most productive languages for backend development.

Major projects like Docker, Kubernetes, and Terraform are written in Go, making it an essential skill for DevOps and cloud engineering.

Fun fact: Go compiles to a single binary with no external dependencies, making deployment incredibly simple.

1. Go Basics & Syntax

Variables, Types & Constants

Go is statically typed — every variable has a fixed type. You can declare variables explicitly with var or use the short declaration := for type inference. Constants are declared with const.

package main

import "fmt"

func main() {
    // Explicit declaration
    var name string = "Gopher"
    var age int = 5

    // Short declaration (type inferred)
    language := "Go"
    version := 1.21

    // Multiple variables
    var x, y int = 10, 20

    // Constants
    const Pi = 3.14159
    const AppName = "MyGoApp"

    fmt.Println(name, age, language, version)
    fmt.Println(x + y)
    fmt.Println(Pi, AppName)
}

Control Flow: if, for, switch

Go has no while loop — for handles all iteration. Switch statements don't fall through by default, making them safer than C-style switches.

package main

import "fmt"

func main() {
    // if-else
    score := 85
    if score >= 90 {
        fmt.Println("Grade: A")
    } else if score >= 75 {
        fmt.Println("Grade: B")
    } else {
        fmt.Println("Grade: C")
    }

    // for loop (basic)
    for i := 0; i < 5; i++ {
        fmt.Println("Count:", i)
    }

    // for as while
    n := 1
    for n < 100 {
        n *= 2
    }

    // range loop
    fruits := []string{"apple", "banana", "mango"}
    for index, fruit := range fruits {
        fmt.Printf("%d: %s
", index, fruit)
    }

    // switch
    day := "Monday"
    switch day {
    case "Monday", "Tuesday":
        fmt.Println("Early week")
    case "Friday":
        fmt.Println("Almost weekend!")
    default:
        fmt.Println("Midweek")
    }
}

2. Functions & Packages

Defining Functions

Go functions can return multiple values, which is commonly used for returning a result and an error together. Functions are first-class citizens and can be passed as arguments.

package main

import (
    "errors"
    "fmt"
)

// Basic function
func greet(name string) string {
    return "Hello, " + name + "!"
}

// Multiple return values
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

// Variadic function
func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

func main() {
    fmt.Println(greet("World"))

    result, err := divide(10, 3)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Printf("Result: %.2f
", result)
    }

    fmt.Println(sum(1, 2, 3, 4, 5)) // 15
}

3. Structs & Interfaces

Structs and Methods

Go uses structs instead of classes. Methods are defined on types using a receiver syntax. Interfaces are satisfied implicitly — no explicit 'implements' keyword needed.

package main

import "fmt"

// Struct definition
type Animal struct {
    Name   string
    Sound  string
    Legs   int
}

// Method on a struct
func (a Animal) Speak() string {
    return fmt.Sprintf("%s says %s", a.Name, a.Sound)
}

// Interface
type Speaker interface {
    Speak() string
}

func makeNoise(s Speaker) {
    fmt.Println(s.Speak())
}

func main() {
    dog := Animal{Name: "Dog", Sound: "Woof", Legs: 4}
    cat := Animal{Name: "Cat", Sound: "Meow", Legs: 4}

    makeNoise(dog)
    makeNoise(cat)

    fmt.Printf("%s has %d legs
", dog.Name, dog.Legs)
}

4. Goroutines & Channels

Goroutines and Channels

Goroutines are lightweight threads managed by the Go runtime. Channels provide a safe way to communicate between goroutines — following the Go mantra: 'Do not communicate by sharing memory; share memory by communicating.'

package main

import (
    "fmt"
    "sync"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d starting
", id)
    // simulate work
    fmt.Printf("Worker %d done
", id)
}

func producer(ch chan<- int) {
    for i := 1; i <= 5; i++ {
        ch <- i
    }
    close(ch)
}

func main() {
    // WaitGroup for goroutines
    var wg sync.WaitGroup
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }
    wg.Wait()

    // Channels
    ch := make(chan int)
    go producer(ch)
    for val := range ch {
        fmt.Println("Received:", val)
    }
}

5. Error Handling

Idiomatic Error Handling

Go treats errors as values rather than exceptions. Functions return errors as the last return value, and callers check them explicitly. You can create custom error types for richer context.

package main

import (
    "errors"
    "fmt"
)

// Custom error type
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message)
}

func validateAge(age int) error {
    if age < 0 {
        return &ValidationError{Field: "age", Message: "must be non-negative"}
    }
    if age > 150 {
        return &ValidationError{Field: "age", Message: "unrealistically large"}
    }
    return nil
}

func main() {
    ages := []int{25, -1, 200}
    for _, age := range ages {
        if err := validateAge(age); err != nil {
            var ve *ValidationError
            if errors.As(err, &ve) {
                fmt.Printf("Field: %s, Issue: %s
", ve.Field, ve.Message)
            }
        } else {
            fmt.Printf("Age %d is valid
", age)
        }
    }
}

6. Standard Library

Common Packages

Go ships with a rich standard library. Common packages include fmt for formatting, net/http for web servers, encoding/json for JSON, and os for system operations.

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strings"
)

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    user := User{Name: "Alice", Email: "alice@go.dev", Age: 30}
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(user)
}

func main() {
    // strings package
    s := "Hello, Go World!"
    fmt.Println(strings.ToUpper(s))
    fmt.Println(strings.Contains(s, "Go"))
    fmt.Println(strings.Replace(s, "Go", "Golang", 1))

    // JSON marshal
    user := User{Name: "Bob", Email: "bob@go.dev", Age: 25}
    data, _ := json.Marshal(user)
    fmt.Println(string(data))

    // Simple HTTP server
    http.HandleFunc("/user", handler)
    fmt.Println("Server running on :8080")
    // http.ListenAndServe(":8080", nil)
}

Keep Building with Go!

Go's simplicity and power make it one of the best languages for building reliable, scalable software. From microservices to CLI tools, Go has you covered.

Happy Coding with Go!