Learn in 10 minutes

Learn in 10 minutes

Learn Go in 10 minutes

Go (also known as Golang) is a statically typed, compiled programming language designed at Google. It’s known for its simplicity, efficiency, and excellent support for concurrency. This tutorial will help you quickly learn Go programming.

1. Writing Your First Go Program

Let’s start with a simple program. Create a file named hello.go and enter the following code:

package main

import "fmt"

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

Save the file and run the following command in the terminal:

go run hello.go

The output will be:

Hello, World!

This simple program demonstrates Go’s basic structure:

  • package main declares the package name
  • import "fmt" imports the format package for I/O operations
  • func main() is the entry point of the program
  • fmt.Println() prints text to the console

2. Basic Syntax

Go has a clean and simple syntax. Unlike Python, Go uses curly braces {} to define code blocks and requires semicolons at the end of statements (though they’re usually inserted automatically).

// This is a single-line comment
fmt.Println("Hello, World!")

/*
This is a multi-line comment
spanning multiple lines
*/

Basic syntax rules in Go:

  • Code Blocks: Defined by curly braces {}
  • Comments: Single-line comments start with //, multi-line with /* */
  • Statements: End with semicolons (automatically inserted)
  • Package Declaration: Every file starts with a package declaration

3. Variables and Data Types

Go is statically typed, meaning you must declare variable types. However, Go supports type inference with the := operator.

Variable declaration methods:

// Explicit type declaration
var name string = "John"
var age int = 25

// Type inference
name := "John"
age := 25

// Multiple variable declaration
var x, y int = 10, 20
x, y := 10, 20

Go’s main basic data types:

  • Integer types: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr
  • Float types: float32, float64
  • String: string
  • Boolean: bool
  • Complex types: complex64, complex128

3.1 Numeric Types

Go provides various numeric types for different use cases:

// Integer types
var age int = 25
var smallNumber int8 = 127
var largeNumber int64 = 9223372036854775807

// Float types
var temperature float32 = 36.5
var pi float64 = 3.14159265359

// Complex numbers
var complexNum complex64 = 3 + 4i

3.2 String Type

Strings in Go are sequences of bytes and are immutable:

// String declaration
var greeting string = "Hello, Go!"
name := "Alice"

// String operations
fmt.Println(len(greeting))        // String length
fmt.Println(greeting[0])          // Access first character (byte)
fmt.Println(greeting[0:5])        // String slicing
fmt.Println(strings.ToUpper(name)) // Convert to uppercase

3.3 Boolean Type

Boolean type has two values: true and false:

var isActive bool = true
var isComplete bool = false

// Boolean operations
result1 := true && false  // false
result2 := true || false  // true
result3 := !true          // false

4. Constants

Constants are declared using the const keyword and cannot be changed:

const Pi = 3.14159
const MaxUsers = 1000

// Multiple constants
const (
    StatusOK = 200
    StatusNotFound = 404
    StatusError = 500
)

// Typed constants
const Version string = "1.0.0"

5. Data Structures

Go provides several built-in data structures for storing and manipulating data.

5.1 Arrays

Arrays are fixed-size sequences of elements of the same type:

// Array declaration
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
names := [3]string{"Alice", "Bob", "Charlie"}

// Accessing elements
fmt.Println(numbers[0])  // 1
numbers[0] = 10         // Modify element

// Array length
fmt.Println(len(numbers)) // 5

5.2 Slices

Slices are dynamic arrays that can grow and shrink:

// Slice declaration
numbers := []int{1, 2, 3, 4, 5}
var emptySlice []int

// Creating slices from arrays
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4]  // [2, 3, 4]

// Slice operations
numbers = append(numbers, 6)      // Add element
numbers = append(numbers, 7, 8, 9) // Add multiple elements

// Slice capacity and length
fmt.Println(len(numbers)) // Length: 9
fmt.Println(cap(numbers)) // Capacity: 10 (may vary)

5.3 Maps

Maps are unordered collections of key-value pairs:

// Map declaration
student := map[string]interface{}{
    "name": "John",
    "age":  20,
    "major": "Computer Science",
}

// Alternative declaration
var scores map[string]int = make(map[string]int)
scores["math"] = 95
scores["science"] = 88

// Accessing and modifying
fmt.Println(student["name"])
student["age"] = 21
student["gpa"] = 3.8

// Safe access
if phone, exists := student["phone"]; exists {
    fmt.Println(phone)
} else {
    fmt.Println("Phone not provided")
}

// Iterating over map
for key, value := range student {
    fmt.Printf("%s: %v\n", key, value)
}

5.4 Structs

Structs are collections of fields that can have different types:

// Struct definition
type Person struct {
    Name string
    Age  int
    City string
}

// Creating struct instances
person1 := Person{"Alice", 25, "New York"}
person2 := Person{
    Name: "Bob",
    Age:  30,
    City: "London",
}

// Accessing fields
fmt.Println(person1.Name)
person1.Age = 26

6. Operations and Operators

Go provides a rich set of operators for various computations and comparisons.

  • Arithmetic Operators: +, -, *, /, % (modulus)
  • Comparison Operators: ==, !=, >, <, >=, <=
  • Logical Operators: &&, ||, !
  • Bitwise Operators: &, |, ^, <<, >>
  • Assignment Operators: =, +=, -=, *=, /=

6.1 Arithmetic Operators

a, b := 10, 3

fmt.Printf("Addition: %d\n", a + b)      // 13
fmt.Printf("Subtraction: %d\n", a - b)   // 7
fmt.Printf("Multiplication: %d\n", a * b)  // 30
fmt.Printf("Division: %d\n", a / b)      // 3
fmt.Printf("Modulus: %d\n", a % b)      // 1

6.2 Comparison Operators

x, y := 5, 10

fmt.Printf("Equal: %t\n", x == y)     // false
fmt.Printf("Not equal: %t\n", x != y) // true
fmt.Printf("Greater than: %t\n", x > y)  // false
fmt.Printf("Less than: %t\n", x < y)  // true

6.3 Logical Operators

a, b := true, false

fmt.Printf("AND operation: %t\n", a && b)  // false
fmt.Printf("OR operation: %t\n", a || b)    // true
fmt.Printf("NOT operation: %t\n", !a)    // false

7. Control Flow

Go provides several control flow statements to manage program execution.

7.1 if Statements

age := 20
if age >= 18 {
    fmt.Println("Adult")
} else if age >= 13 {
    fmt.Println("Teen")
} else {
    fmt.Println("Child")
}

// if with short statement
if score := 85; score >= 90 {
    fmt.Println("Grade: A")
} else if score >= 80 {
    fmt.Println("Grade: B")
} else {
    fmt.Println("Grade: C")
}

7.2 for Loops

Go has only one loop construct: for

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

// While-style loop
count := 0
for count < 5 {
    fmt.Println(count)
    count++
}

// Infinite loop
for {
    fmt.Println("This will run forever")
    break // Use break to exit
}

// Range loop (for slices, arrays, maps)
fruits := []string{"apple", "banana", "cherry"}
for index, fruit := range fruits {
    fmt.Printf("%d: %s\n", index, fruit)
}

7.3 switch Statements

day := "Monday"
switch day {
case "Monday":
    fmt.Println("Start of the week")
case "Friday":
    fmt.Println("Weekend is near")
case "Saturday", "Sunday":
    fmt.Println("Weekend!")
default:
    fmt.Println("Regular day")
}

// Switch with no expression
score := 85
switch {
case score >= 90:
    fmt.Println("Grade: A")
case score >= 80:
    fmt.Println("Grade: B")
case score >= 70:
    fmt.Println("Grade: C")
default:
    fmt.Println("Grade: F")
}

8. Functions

Functions in Go are first-class citizens and support multiple return values.

8.1 Basic Functions

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

// Calling the function
message := greet("John")
fmt.Println(message)

8.2 Multiple Return Values

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("cannot divide by zero")
    }
    return a / b, nil
}

// Using multiple return values
result, err := divide(10, 2)
if err != nil {
    fmt.Println("Error:", err)
} else {
    fmt.Println("Result:", result)
}

8.3 Named Return Values

func calculateRectangle(width, height float64) (area float64, perimeter float64) {
    area = width * height
    perimeter = 2 * (width + height)
    return // naked return
}

area, perimeter := calculateRectangle(5, 3)
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", area, perimeter)

8.4 Variadic Functions

func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

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

9. Pointers

Go has pointers but with simpler syntax than C/C++:

func modifyValue(x *int) {
    *x = *x * 2
}

func main() {
    value := 10
    fmt.Println("Before:", value) // 10

    modifyValue(&value)
    fmt.Println("After:", value)  // 20
}

10. Methods

Methods are functions with a receiver argument:

type Rectangle struct {
    Width  float64
    Height float64
}

// Method with value receiver
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Method with pointer receiver
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

rect := Rectangle{Width: 5, Height: 3}
fmt.Println("Area:", rect.Area()) // 15

rect.Scale(2)
fmt.Println("Scaled Area:", rect.Area()) // 60

11. Interfaces

Interfaces define method signatures that types can implement:

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * 3.14159 * c.Radius
}

func printShapeInfo(s Shape) {
    fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

circle := Circle{Radius: 5}
printShapeInfo(circle)

12. Error Handling

Go uses explicit error handling rather than exceptions:

func readFile(filename string) (string, error) {
    data, err := os.ReadFile(filename)
    if err != nil {
        return "", fmt.Errorf("failed to read file %s: %w", filename, err)
    }
    return string(data), nil
}

content, err := readFile("example.txt")
if err != nil {
    fmt.Println("Error:", err)
    return
}
fmt.Println("Content:", content)

13. Concurrency with Goroutines

Goroutines are lightweight threads managed by the Go runtime:

func worker(id int) {
    for i := 0; i < 3; i++ {
        fmt.Printf("Worker %d: %d\n", id, i)
        time.Sleep(time.Millisecond * 100)
    }
}

func main() {
    // Start multiple goroutines
    for i := 1; i <= 3; i++ {
        go worker(i)
    }

    // Wait for goroutines to complete
    time.Sleep(time.Second)
    fmt.Println("All workers completed")
}

14. Channels

Channels are used for communication between goroutines:

func producer(ch chan<- int) {
    for i := 0; i < 5; i++ {
        ch <- i // Send value to channel
        time.Sleep(time.Millisecond * 100)
    }
    close(ch) // Close channel when done
}

func consumer(ch <-chan int) {
    for value := range ch {
        fmt.Println("Received:", value)
    }
}

func main() {
    ch := make(chan int, 3) // Buffered channel

    go producer(ch)
    consumer(ch)

    fmt.Println("Channel communication completed")
}

15. File Operations

Go provides simple methods for reading and writing files:

// Reading files
data, err := os.ReadFile("example.txt")
if err != nil {
    fmt.Println("Error reading file:", err)
    return
}
fmt.Println("File content:", string(data))

// Writing files
content := "Hello, Go!\n"
err = os.WriteFile("output.txt", []byte(content), 0644)
if err != nil {
    fmt.Println("Error writing file:", err)
    return
}
fmt.Println("File written successfully")

16. Packages and Modules

Go modules manage dependencies and package versions:

// Importing standard library packages
import (
    "fmt"
    "math"
    "strings"
)

func main() {
    fmt.Println(math.Sqrt(16))        // 4
    fmt.Println(strings.ToUpper("go")) // GO
}

To create your own package, create a directory with your package name and export functions by capitalizing their names.

17. Testing

Go has built-in testing support:

// In file math_test.go
package main

import "testing"

func TestAdd(t *testing.T) {
    result := add(2, 3)
    expected := 5
    if result != expected {
        t.Errorf("add(2, 3) = %d; want %d", result, expected)
    }
}

func add(a, b int) int {
    return a + b
}

Run tests with: go test

18. Best Practices

  • Use gofmt to format your code
  • Follow Go naming conventions (camelCase for variables, PascalCase for exports)
  • Handle errors explicitly
  • Use interfaces for abstraction
  • Prefer composition over inheritance
  • Write comprehensive tests
  • Use the standard library whenever possible

This tutorial covers the essential features of Go programming. With practice, you’ll be able to build efficient and concurrent applications using Go’s powerful features.