Olha Stefanishyna
← Back to home

Go for Developers: Setup, Variables, and Basic Types

A minimalist abstract technical illustration featuring a network of intersecting circuit lines, nodes, and geometric overlays in a palette of beige, white, and soft gray.
A minimalist abstract technical illustration featuring a network of intersecting circuit lines, nodes, and geometric overlays in a palette of beige, white, and soft gray.

Introduction

In the intro I discussed why fundamentals matter. Now let's actually start learning them. In this series I will outline main principles and first steps needed to get started.

Let's go.

Go is compiled directly to machine code. It is statically and strongly typed, and handles concurrency using Goroutines - lightweight concurrent functions managed by the Go runtime.

In a statically typed language, you must declare the type of a variable before using it. Strongly typed means the type of a variable is strictly enforced. Once declared, it cannot be used as another type. In Go, variable types are known at compile time, but the compiler can infer them for you.

Go was designed to be readable and unsurprising. Coming from dynamically typed languages such as JavaScript, you'll find a lot of familiar ideas: functions, loops, conditionals, but with stricter rules.

Setup Environment

To set up the environment and install Go on your machine, download the package from official website and check version by running go version. Don't forget to restart your terminal to update PATH environment variable.

To initialize project and enable dependency tracking use

bash
1# create project folder
2mkdir my-first-go-app
3
4# move inside
5cd my-first-go-app
6
7# initialize module
8go mod init my-first-go-app

go mod init [module-path] will create a new module go.mod file at the current directory to track code's dependencies. In the beginning the file will include only the name of your module and the Go version.

Hello World in Go.

Now, let's say Hello World in Go. In your current directory create a file named main.go and write there:

go
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Println("Hello, World!")
7}

Compared to JS it looks massive:

javascript
1console.log('Hello World');

What is going on there:

  • Every Go file belongs to a package. Executable programs use package main.
  • main() is the entry point - just like in C.
  • fmt is the standard library package. It contains functions for formatting text, including printing to the console.

Coming from JS, it's important to note that Go distinguishes between strings and single characters: the double quotes (" ") or backticks (` `) are used to create string. These are sequences of bytes (usually UTF-8 encoded text). The single quotes (' ') create rune. This represents a single Unicode code point (essentially an int32).

To compile and run this code, type in the terminal go run main.go to specify an entry point. Or use go run . to target the package in the current directory.

When you execute go run, the Go compiler creates a binary file in a temporary directory on your computer. It compiles the code, executes the resulting binary and immediately deletes the binary after the program finishes.

go run is intended for development and quick testing. To get the actual compiled executable file, use: go build main.go. It will generate executable file in your current folder.

Variables

In Go variables are declared with var. Their values can be changed after declaration. They can be declared in several ways and the way they are declared matters more than it might seem at first.

  • Explicit declaration with type var x int. In this case, x is declared as an integer. You can declare this way, but if you don't use it later, your program will not be compiled. This strict rule applies to local variables.

  • Declaration with initialization var y int = 10. Here, y is declared as an integer and initialized with the value 10.

  • Type inference: Go can infer the type of a variable if it is initialized with a value var z = 20. The type of z is inferred as int.

  • Short Variable Declaration. It only works inside functions. In short declaration Go infers the type automatically. You still cannot change its type: a := 30. Here, a is declared and initialized with the value 30. The type of a is inferred as int.

  • Multiple variable declaration:

go
1var (
2 b int
3 c string = "hello"
4)

In this example, b is declared as an integer, and c is declared as a string with the value "hello".

  • Short Declaration for Multiple Variables:
go
1d, e := 40, "world"

Here, d is declared as an integer with the value 40, and e is declared as a string with the value "world".

Zero Values

Unlike JS where uninitialized variables are undefined, Go variables always have a zero value:

go
1var i int // 0
2var f float64 // 0
3var b bool // false
4var s string // "" (empty string, not nil!)
5var p *int // nil (for pointer types)

They say it eliminates a whole class of bugs around uninitialized state.

Constants

Constants declared with const are immutable. Once declared, their values cannot be changed. Constants must be initialized at the time of declaration and cannot be modified later. Used for values that should not change throughout the program, such as configuration values, mathematical constants, or fixed settings.

go
1const Pi = 3.14159
2const AppName = "mytool"
3const MaxRetries int = 3

Basic Types

We already know that Go is statically typed, meaning that once a variable type is defined, it can only store data of that type. Go comes with a set of built-in types. You can also define your own. Here is the top-level split:

text
1All Go Types
2├── Built-in Types (predeclared by the language itself)
3│ ├── Basic Types
4│ └── Composite Types
5└── Defined (Named) Types
6 ├── Type Definitions
7 └── Type Aliases

Types are a very vast topic in Go, let's just look at some basic types.

go
1// Booleans
2var isReady bool = true
3
4// Integers
5var count int = 42
6var port int32 = 8080
7var big int64 = 9000000000
8
9// Unsigned integers
10var id uint = 1
11
12// Floats
13var price float64 = 9.99
14var ratio float32 = 0.5
15
16// Strings (immutable, UTF-8 encoded)
17var lang string = "Go"
18
19// Rune (alias for int32 - represents a Unicode code point)
20var r rune = '🚀'

Go has two categories of numeric types that differ in how their size is determined: fixed-size and platform-dependent.

The first type, a fixed-size type, means that the size of the data in bits does not change, regardless of the architecture of a machine that the code is compiled for. For example, using int32 ensures that the size of the integer is consistent across different platforms:

go
1var count int32 = 42

The second type is a platform-dependent type. Its bit size is determined at compile time based on the target architecture and can vary from platform to platform. In this example it will be 32 bits when compiled for a 32-bit target, and 64 bits when compiled for a 64-bit target:

go
1var count int = 42

For developers coming from dynamically typed languages, this is worth keeping in mind, because in dynamically typed languages like JavaScript, you never choose between int32 and int64. In Go, that choice is yours, and it has real consequences for cross-platform behavior.

In addition to data types having different sizes, types like integers also come in two basic types: signed and unsigned. An int8 is a signed integer, and can have a value from -128 to 127. A uint8 is an unsigned integer, and can only have a positive value of 0 to 255.

In the next article I'll proceed with types as they play a huge role in building a mental model of any language.

Let's talk