No history yet

Go Syntax and Basics

The Building Blocks

Every Go program is organized into packages. Think of a package as a container for your code. The starting point for any executable program is the main package, which must contain a function called main.

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
}

In this classic "Hello, World!" example, we import the fmt package, which provides functions for formatting and printing text. The main function is where the program's execution begins.

Variables in Go store data. You can declare a variable using the var keyword, followed by the variable name and its type.

// Declaring a variable of type string
var message string = "This is a message."

// You can also let Go infer the type
var score = 100 // Go knows this is an integer

Inside a function, there's a more common, shorter way to declare and initialize variables using the := operator. This is called a short variable declaration. It automatically infers the data type.

func someFunction() {
    // Using the short declaration operator
    name := "Alice"
    age := 30
    
    // 'name' is a string, 'age' is an int
}

When you have a value that should never change, you use a constant. Constants are declared with the const keyword. They are a good way to make your code clearer and prevent accidental changes to important values.

const Pi = 3.14159
const IsProduction = false

Types and Data

Go is a statically typed language. This means that once a variable is declared with a certain type, it can only hold values of that type. This check happens when the code is compiled, which helps catch many bugs early.

Here are some of the most common basic types:

TypeDescriptionExample
intIntegers (whole numbers)42, -10
float64Floating-point numbers (decimals)3.14, -0.01
boolBoolean values, either true or falsetrue
stringA sequence of characters"Hello, world!"

When you declare a variable without giving it an initial value, Go automatically assigns it a "zero value." For numbers, this is 0. For booleans, it's false, and for strings, it's an empty string "".

var i int      // i is 0
var f float64  // f is 0.0
var b bool     // b is false
var s string   // s is "" (empty string)

Flow and Logic

Programs rarely run straight from top to bottom. They need to make decisions and repeat actions. Go provides simple and powerful control structures for this.

The if statement executes a block of code if a condition is true. You can add an else block to run code when the condition is false. Unlike many other languages, Go doesn't require parentheses () around the condition.

score := 85

if score >= 90 {
    fmt.Println("Grade: A")
} else if score >= 80 {
    fmt.Println("Grade: B")
} else {
    fmt.Println("Grade: C or lower")
}

Go has only one looping keyword: for. It's versatile enough to replace the for, while, and do-while loops found in other languages.

// A standard for loop
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// A loop that acts like a 'while' loop
count := 0
for count < 3 {
    fmt.Println("Still going...")
    count++
}

For comparing a single value against multiple possibilities, a switch statement is often cleaner than a series of if-else statements. Go's switch is very flexible. Cases don't automatically "fall through" to the next one, which is a common source of bugs in other languages.

day := "Wednesday"

switch day {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
    fmt.Println("It's a weekday.")
case "Saturday", "Sunday":
    fmt.Println("It's the weekend!")
default:
    fmt.Println("Not a valid day.")
}

Functions and Errors

Functions are reusable blocks of code that perform a specific task. They help organize your program and make it more readable. A function is defined with the func keyword, a name, a list of parameters, and the return type(s).

// A function that takes two integers and returns their sum
func add(x int, y int) int {
    return x + y
}

A distinctive feature of Go is that functions can return multiple values. This is especially important for error handling. It's standard practice in Go for a function that might fail to return its result along with an error value. If the operation succeeds, the error is nil (Go's equivalent of null). If it fails, the error will contain information about what went wrong.

By convention, the error is always the last value returned from a function.

Here's a function that divides two numbers. Since division by zero is an error, the function returns both the result and an error value.

import (
    "fmt"
    "errors"
)

// divide returns a float64 and an error
func divide(a, b float64) (float64, error) {
    if b == 0 {
        // Create a new error
        return 0, errors.New("cannot divide by zero")
    }
    // No error, so return nil for the error value
    return a / b, nil
}

func main() {
    result, err := divide(10.0, 2.0)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", result)
    }

    result, err = divide(10.0, 0.0)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", result)
    }
}

This pattern of checking for err != nil immediately after calling a function is fundamental to writing solid Go code. It makes error handling explicit and easy to follow.

Time to test your knowledge of these core concepts.

Quiz Questions 1/5

What is the required package and function name for the entry point of an executable Go program?

Quiz Questions 2/5

What is the primary purpose of Go's ability for functions to return multiple values?

You now have the basic building blocks for writing programs in Go. With variables, types, control flow, and functions, you can start creating simple yet powerful applications.