Learn Go · Part 1 of 11

Introduction to Go

What makes Go different from other languages, getting it installed, and writing and running your first program.

Video 0:00–6:25 · 6 topics · 4 exercises

All parts · this is part 1
  1. 1.Introduction to Go
  2. 2.Constants, Variables and Basic Data Types
  3. 3.Functions and Control Structures
  4. 4.Arrays, Slices, Maps and Loops
  5. 5.Strings, Runes and Bytes
  6. 6.Structs and Interfaces
  7. 7.Pointers
  8. 8.Goroutines
  9. 9.Channels
  10. 10.Generics
  11. 11.Building an API

Extras

Learn GO Fast: Full Tutorial

Static and strong typing

First thing to know: Go is statically typed. When you make a variable, you either tell Go what type it is, or you give it a value right away so Go can figure it out. Either way, once it's set, that type is locked in. Want a different type? You have to convert it yourself (more on that in part 2).

Go is also strongly typed, which means what you can do with a variable depends on its type. So you can't add an int and a string together. JavaScript will happily let you do 1 + "2" and hand you back "12". Go just says no.

main.gogo
package main

import "fmt"

func main() {
	var myVariable string = "hello" // the type, written out
	inferred := "hello"             // the type, worked out from the value

	fmt.Println(myVariable, inferred)

	// myVariable = 42           // won't compile: 42 isn't a string
	// fmt.Println(inferred + 1) // won't compile: can't add a string and an int
}

People mix these two up all the time, so here's the quick version. Static vs dynamic is about when types get checked: before your code runs, or while it's running. Strong vs weak is about how picky the checks are. Python is dynamic but pretty strong. C is static but lets you get away with a lot.

Practice

  • Warm-upWhat type is it?

    What type does Go give each of these, or does it not compile at all? var a = 3, var b = 3.0, c := "3", var d int = "3".

    Practice with AI

Compiled, fast, and built for concurrency

Go is compiled. The compiler turns your code into machine code and spits out a single binary you can just run. No interpreter, nothing extra to install on the machine you run it on. Python, on the other hand, is interpreted, so it's translating your code line by line while it runs, and that adds up.

How much does it add up? In the video I counted to 100 million in both. Python took about 6 seconds on my machine, and Go took about 50 milliseconds. Here's the code if you want to try it yourself:

main.gogo
package main

import (
	"fmt"
	"time"
)

func main() {
	start := time.Now()
	count := 0
	for i := 0; i < 100_000_000; i++ {
		count++
	}
	fmt.Println(count, "in", time.Since(start))
}

A few other things Go has going for it:

FeatureWhy you care
Fast compile timesYou can write some code, compile it and test it pretty much right away. No waiting around.
Concurrency built inGoroutines and channels are part of the language, no extra packages needed. We get into these in parts 8 and 9.
Garbage collectionMemory you're done with gets freed up for you, so it's not something you have to manage yourself.
SimplicityThe language is pretty small, so you can do a lot without writing a ton of code, and other people's Go is usually easy to read.

Installing Go

The easiest way to get Go is to head to go.dev/doc/install and pick your platform. On Mac and Windows you just download the installer and run it. On Linux you unpack a file and add Go to your PATH.

To check it worked, run this in a terminal:

terminaltext
$ go version
go version go1.24.4 darwin/arm64

If you get something like that, we're good to go.

As for an editor, use whatever you want: VS Code with the Go extension, GoLand, Vim, Neovim (that's what I use). Just make sure it's hooked up to gopls, Go's language server, so you get autocomplete and errors as you type.

Modules and packages

Before we write any code, there are two things to know about how Go code is organized: packages and modules.

  • A package is just a folder with some .go files in it. Every file in that folder starts with the same package line.
  • A module is a bunch of packages together. When you start a new project, you're really starting a new module.

So let's make one. Make a folder, cd into it, and run go mod init with your module's name:

terminaltext
$ mkdir go-tutorials && cd go-tutorials
$ go mod init github.com/you/go-tutorials

You can call it whatever you want, but usually it's named after where it lives on GitHub, since that's how other people would import it. This creates a go.mod file:

go.modgo
module github.com/you/go-tutorials

go 1.24

Right now it's just the module name and the Go version. Once we start installing other people's packages, they'll show up in here too, with their versions (we do that in part 11). Here's how we'll lay things out for now:

layouttext
go-tutorials/
├── go.mod                  the module: its name and Go version
└── cmd/
    └── tutorial_1/         a package (a folder of .go files)
        └── main.go

To import one of your own packages, you use the module name plus the folder it's in. So if we add a greetings package, main imports it like this:

two packagesgo
// greetings/greetings.go
package greetings

// Hello starts with a capital letter, so other packages can call it.
func Hello(name string) string {
	return "Hello, " + name
}

// cmd/tutorial_1/main.go
package main

import (
	"fmt"

	"github.com/you/go-tutorials/greetings"
)

func main() {
	fmt.Println(greetings.Hello("Gopher"))
}

Practice

  • PracticeAdd your own package

    The template has a main.go and a mathutil package. Fill in Double(n int) int so main prints 42. Then main also calls mathutil.triple(14), which doesn't compile: fix the mathutil package so it does, and say why it didn't.

    Practice with AI

Your first program

Time to write some code. Make a main.go file in cmd/tutorial_1:

cmd/tutorial_1/main.gogo
package main

import "fmt"

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

So what's going on here?

  • package main is a special package name. It tells the compiler "this is a program, start here".
  • The compiler then looks for a function called main in that package, and that's the first thing that runs. This only applies to main, by the way. If you had a package called blue, you wouldn't need a function called blue.
  • import "fmt" pulls in Go's built-in formatting package, and fmt.Println prints whatever you give it plus a new line.
  • The opening curly brace has to be on the same line as func main(). Put it on the next line and you get an error.

Practice

  • PracticeFix it

    This program won't run: it says package app at the top, imports fmt and os, and has func Main(). Find all three problems and fix them.

    Practice with AI
  • Warm-upHello, you

    The template reads your name and your favorite language. Print the name on one line and the language on the next with fmt.Println.

    Practice with AI

go build and go run

Now let's run it. You've got two options:

terminaltext
go build cmd/tutorial_1/main.go   # writes a binary called main
./main                            # runs it: Hello, World!

go run cmd/tutorial_1/main.go     # compiles to a temporary binary and runs it
go build -o hello ./cmd/tutorial_1  # name the binary yourself

go build gives you a binary you can run whenever you want. go run does the build and the run in one command, and honestly it's what I use most of the time while I'm working on something.

Since the binary has everything it needs baked in, you can copy it to another machine with the same OS and it'll just run. You can even build for a different OS than the one you're on. Here's building a Linux binary from a Mac:

terminaltext
GOOS=linux GOARCH=amd64 go build -o hello-linux ./cmd/tutorial_1

And that's it, you just wrote and ran your first Go program. Pretty cool.