No history yet

Go Basics

Welcome to Go

Go, often called Golang, is a programming language created at Google. It was designed to be simple, efficient, and reliable. Think of it as having the performance of a language like C++ but with a much cleaner and more readable syntax, like Python.

Every Go program is made up of packages. Programs start running in the main package, and the code execution begins at the main function. Let's look at the classic "Hello, World!" example to see the basic structure.

package main

import "fmt"

// This is the main function where the program starts.
func main() {
    fmt.Println("Hello, World!")
}

In this example, package main tells the compiler this is an executable program. The import "fmt" line includes a package from Go's standard library, which contains functions for formatting text, like printing to the console. The main function holds the code that will run.

Variables and Data Types

Variables are containers for storing data. In Go, you can declare a variable and its type, or you can let the compiler figure out the type for you. Go is a statically typed language, which means once a variable's type is set, it can't be changed.

Here are some of the basic data types you'll use constantly:

  • int: Whole numbers, like -10, 0, or 42.
  • float64: Numbers with a decimal point, like 3.14 or -0.001.
  • string: A sequence of characters, like "hello".
  • bool: Can be either true or false.

You can declare variables using the var keyword, or for a shorter version inside functions, you can use :=.

package main

import "fmt"

func main() {
    // Using the 'var' keyword
    var greeting string = "Hello from a variable!"
    fmt.Println(greeting)

    // Using short assignment := (most common)
    answer := 42
    pi := 3.14159
    isGoFun := true

    fmt.Println("The answer is", answer)
    fmt.Println("Pi is roughly", pi)
    fmt.Println("Is Go fun?", isGoFun)
}

Controlling the Flow

Programs rarely run straight through from top to bottom. You often need to make decisions or repeat actions. This is where control structures come in. Go has a few simple but powerful tools for managing program flow.

For making decisions, you use if and else. If a condition is true, one block of code runs; otherwise, another block runs.

For repetition, Go has one looping construct: the for loop. It's very versatile and can be used as a traditional for loop, a while loop, or even an infinite loop.

A switch statement is a cleaner way to write a long series of if-else statements when you're comparing a single value against many possibilities.

package main

import "fmt"

func main() {
    // if-else statement
    score := 85
    if score > 90 {
        fmt.Println("Grade: A")
    } else {
        fmt.Println("Grade: Not an A")
    }

    // for loop
    for i := 0; i < 3; i++ {
        fmt.Println("Looping:", i)
    }

    // switch statement
    day := "Tuesday"
    switch day {
    case "Monday":
        fmt.Println("It's the start of the week.")
    case "Friday":
        fmt.Println("Weekend is almost here!")
    default:
        fmt.Println("It's a regular day.")
    }
}

Go's Superpower Concurrency

One of Go's most famous features is how it handles concurrency, which is the ability to have multiple tasks running at the same time. Instead of complex threads, Go gives us two simple tools: goroutines and channels.

Imagine you're running a coffee shop. You could have one person taking orders, making coffee, and serving it. This is slow. Or, you could have multiple baristas working at once. That's concurrency.

A goroutine is like a lightweight thread. It's a function that can run concurrently with other functions.

You can start a new goroutine by simply putting the go keyword before a function call. It's incredibly cheap to create thousands of them without slowing your system down. They're your concurrent baristas.

But how do they coordinate? If two baristas try to use the same espresso machine at the same time, you have a problem. They need a way to communicate safely.

A channel is a pipe that connects concurrent goroutines. You can send and receive values through channels, allowing them to communicate and synchronize.

Channels are the conveyor belts in our coffee shop. One barista can place a finished coffee on the belt (sending to the channel), and another can pick it up for the customer (receiving from the channel). This prevents them from crashing into each other.

Here’s a simple example showing a goroutine and a channel in action.

package main

import (
    "fmt"
    "time"
)

func say(text string, c chan string) {
    time.Sleep(1 * time.Second) // Simulate work
    c <- text // Send the text into the channel
}

func main() {
    // Create a channel of type string
    messageChannel := make(chan string)

    // Start a goroutine
    go say("Hello from the goroutine!", messageChannel)

    fmt.Println("Waiting for the message...")

    // Wait and receive the message from the channel
    msg := <-messageChannel
    fmt.Println(msg)
}

In this code, the main function starts a say goroutine and then waits to receive a message from messageChannel. The program only continues after the goroutine sends its message, demonstrating safe communication.

Now, let's test your understanding of these core concepts.

Quiz Questions 1/6

What is the name of the function where an executable Go program begins its execution?

Quiz Questions 2/6

True or False: Go is a statically typed language, which means a variable's type cannot be changed after it is declared.

That covers the absolute basics of Go. With these building blocks, you have the foundation to start writing simple yet powerful programs.