Cristhian Villegas
Backend9 min read1 views

Go Course #2: Variables, Data Types and Constants in Go

Go Course #2: Variables, Data Types and Constants in Go

Introduction: Variables and Types in Go - Part 2 of 10

Go Logo

Welcome to Part 2 of 10 of the Go Programming Course from Scratch. In the previous article, we installed Go and wrote our first Hello World program. Now we will learn the fundamental concepts you will use in absolutely every program you write: variables, data types, and constants.

Go is a statically typed language, which means that every variable has a type defined at compile time. This might seem restrictive at first if you come from languages like Python or JavaScript, but it is a huge advantage: the compiler catches errors before your program runs.

Note: This article is Part 2 of 10 of the course. If you have not read Part 1 (installation and Hello World), we recommend starting there.

Basic Data Types in Go

Go has a well-defined set of primitive types. These are the ones you will use most frequently:

Integer Numeric Types

TypeSizeRange
int32 or 64 bits (platform dependent)Signed integer
int88 bits-128 to 127
int1616 bits-32768 to 32767
int3232 bits-2 billion to 2 billion
int6464 bitsVery large range
uint32 or 64 bitsPositive numbers only

Floating-Point Numeric Types

TypePrecision
float32Single precision (7 digits)
float64Double precision (15 digits) - most commonly used

Other Fundamental Types

  • string: Text string (immutable in Go)
  • bool: Boolean value (true or false)
  • byte: Alias for uint8, used for binary data
  • rune: Alias for int32, represents a Unicode character
go
1package main
2
3import "fmt"
4
5func main() {
6    var integer int = 42
7    var decimal float64 = 3.14159
8    var text string = "Hello Go"
9    var active bool = true
10    var letter byte = 'A'
11    var emoji rune = '🚀'
12
13    fmt.Println(integer, decimal, text, active, letter, string(emoji))
14}
Recommendation: In most cases, use int for integers and float64 for decimals. Only use specifically sized types (int32, int64) when you need precise memory control or are working with APIs that require them.

Variable Declaration: var and :=

Go offers several ways to declare variables. Let us look at each one:

Declaration with var (long form)

go
1package main
2
3import "fmt"
4
5func main() {
6    // Declaration with explicit type and value
7    var name string = "Carlos"
8    var age int = 30
9
10    // Declaration with type but no value (uses zero value)
11    var salary float64
12    var married bool
13
14    // Multiple declaration in a block
15    var (
16        city    string = "Mexico City"
17        country string = "Mexico"
18        code    int    = 52
19    )
20
21    fmt.Println(name, age)
22    fmt.Println("Salary:", salary, "Married:", married)
23    fmt.Println(city, country, code)
24}

Short declaration with := (most commonly used)

Inside functions, you can use the := operator to declare and initialize variables concisely. Go infers the type automatically:

go
1package main
2
3import "fmt"
4
5func main() {
6    name := "Ana"            // Go infers: string
7    age := 25                // Go infers: int
8    weight := 65.5           // Go infers: float64
9    isStudent := true        // Go infers: bool
10
11    fmt.Printf("Name: %s, Age: %d, Weight: %.1f, Student: %t\n",
12        name, age, weight, isStudent)
13}
Watch out: The := operator only works inside functions. You cannot use it at the package level (outside of functions). For package-level variables, you must use var.

Multiple declaration on a single line

go
1package main
2
3import "fmt"
4
5func main() {
6    // Multiple variables of the same type
7    var a, b, c int = 1, 2, 3
8
9    // Multiple variables with :=
10    x, y, z := "hello", 42, true
11
12    fmt.Println(a, b, c)
13    fmt.Println(x, y, z)
14}

Zero Values

In Go, every variable declared without an initial value automatically receives a zero value according to its type. This is different from other languages where uninitialized variables contain memory garbage or throw errors.

Go Gopher

TypeZero Value
int, float640
string"" (empty string)
boolfalse
Pointers, slices, mapsnil
go
1package main
2
3import "fmt"
4
5func main() {
6    var integer int
7    var decimal float64
8    var text string
9    var boolean bool
10
11    fmt.Printf("int: %d\n", integer)       // 0
12    fmt.Printf("float64: %f\n", decimal)   // 0.000000
13    fmt.Printf("string: '%s'\n", text)     // ''
14    fmt.Printf("bool: %t\n", boolean)      // false
15}
Safety advantage: Go's zero values eliminate an entire category of bugs that exist in languages like C or C++, where uninitialized variables can contain random data.

Type Inference

When you use := or var without an explicit type, Go infers the type based on the assigned value:

go
1package main
2
3import "fmt"
4
5func main() {
6    a := 42          // int (not int8, not int32, always int)
7    b := 3.14        // float64 (not float32)
8    c := "Go"        // string
9    d := true        // bool
10    e := 'A'         // rune (int32), not byte
11
12    fmt.Printf("a: %T\n", a)  // int
13    fmt.Printf("b: %T\n", b)  // float64
14    fmt.Printf("c: %T\n", c)  // string
15    fmt.Printf("d: %T\n", d)  // bool
16    fmt.Printf("e: %T\n", e)  // int32
17}

The %T verb in the fmt package prints the type of a variable. It is very useful for debugging.

Practical rule: Go always infers int for integers (not int32 or int64) and float64 for decimals (not float32). If you need a different specific type, you must declare it explicitly.

Constants with const and iota

Constants are values that do not change during program execution. They are declared with the const keyword:

go
1package main
2
3import "fmt"
4
5func main() {
6    const pi float64 = 3.14159265358979
7    const appName = "MyApp"
8    const maxRetries = 3
9
10    fmt.Println("App:", appName)
11    fmt.Println("Pi:", pi)
12    fmt.Println("Max retries:", maxRetries)
13
14    // This would cause a compile error:
15    // pi = 3.14  // cannot assign to pi
16}

Constants with iota

iota is an enumerated constant generator in Go. It starts at 0 and automatically increments on each line within a const block:

go
1package main
2
3import "fmt"
4
5// Days of the week as enumerated constants
6const (
7    Sunday = iota     // 0
8    Monday            // 1
9    Tuesday           // 2
10    Wednesday         // 3
11    Thursday          // 4
12    Friday            // 5
13    Saturday          // 6
14)
15
16// File sizes using iota with expressions
17const (
18    _  = iota             // ignore first value (0)
19    KB = 1 << (10 * iota) // 1 << 10 = 1024
20    MB                    // 1 << 20 = 1048576
21    GB                    // 1 << 30 = 1073741824
22    TB                    // 1 << 40
23)
24
25func main() {
26    fmt.Println("Monday:", Monday)
27    fmt.Println("Friday:", Friday)
28    fmt.Println("1 KB =", KB, "bytes")
29    fmt.Println("1 MB =", MB, "bytes")
30    fmt.Println("1 GB =", GB, "bytes")
31}
Common pattern: iota is Go's idiomatic way to create enumerations. Other languages have enum as a keyword, but Go uses const + iota to achieve the same thing more flexibly.

Type Conversion (Casting)

Go is strict with types: there are no implicit conversions between different types. You must convert explicitly:

go
1package main
2
3import "fmt"
4
5func main() {
6    // Conversion between numeric types
7    var integer int = 42
8    var decimal float64 = float64(integer)
9    var small int32 = int32(integer)
10
11    fmt.Println(integer, decimal, small)
12
13    // Conversion between string and numbers
14    // You need the strconv package
15    var num int = 65
16    var letter string = string(num)      // This gives "A" (ASCII character), NOT "65"
17    fmt.Println("string(65):", letter)   // A
18
19    // To convert a number to its text representation:
20    // use fmt.Sprintf or strconv.Itoa
21    text := fmt.Sprintf("%d", num)
22    fmt.Println("Sprintf:", text)  // "65"
23}
Caution: string(65) does not produce "65", but "A" (the Unicode character 65). To convert a number to text, use fmt.Sprintf("%d", number) or strconv.Itoa(number). This is a very common mistake among Go beginners.

Conversions with strconv

go
1package main
2
3import (
4    "fmt"
5    "strconv"
6)
7
8func main() {
9    // Integer to string
10    age := 25
11    ageText := strconv.Itoa(age)
12    fmt.Println("Age as text:", ageText)
13
14    // String to integer
15    text := "42"
16    number, err := strconv.Atoi(text)
17    if err != nil {
18        fmt.Println("Error:", err)
19    } else {
20        fmt.Println("Number:", number)
21    }
22
23    // String to float64
24    priceText := "19.99"
25    price, err := strconv.ParseFloat(priceText, 64)
26    if err != nil {
27        fmt.Println("Error:", err)
28    } else {
29        fmt.Println("Price:", price)
30    }
31}

The fmt Package: Println, Printf, and Sprintf

The fmt package is one of the most used in Go. You have already seen Println, but it has much more powerful functions:

fmt.Println: simple printing

go
1fmt.Println("Hello", "world")          // Hello world (adds space and newline)
2fmt.Println("Value:", 42, true)         // Value: 42 true

fmt.Printf: formatted printing

Use format verbs to control how each value is displayed:

VerbDescriptionExample
%dDecimal integerfmt.Printf("%d", 42) -> 42
%fFloating pointfmt.Printf("%.2f", 3.14159) -> 3.14
%sStringfmt.Printf("%s", "Go") -> Go
%tBooleanfmt.Printf("%t", true) -> true
%TType of the variablefmt.Printf("%T", 42) -> int
%vDefault valuefmt.Printf("%v", something)
%+vValue with field namesUseful for structs
go
1package main
2
3import "fmt"
4
5func main() {
6    name := "Go"
7    version := 1.23
8    year := 2009
9    isAwesome := true
10
11    fmt.Printf("Language: %s\n", name)
12    fmt.Printf("Version: %.2f\n", version)
13    fmt.Printf("Created in: %d\n", year)
14    fmt.Printf("Is awesome: %t\n", isAwesome)
15    fmt.Printf("Type of version: %T\n", version)
16
17    // Sprintf returns a string instead of printing
18    summary := fmt.Sprintf("%s was created in %d", name, year)
19    fmt.Println(summary)
20}
Printf vs Println: Use Println for quick prints and Printf when you need control over formatting. Sprintf is the same as Printf but returns the string instead of printing it.

Practical Exercises

Put what you have learned into practice with these exercises. Try to solve them before looking at the solution:

Exercise 1: Personal Profile

Create a program that declares variables for your name, age, height, city, and whether you are a student. Print everything formatted using Printf.

go
1package main
2
3import "fmt"
4
5func main() {
6    name := "Ana Garcia"
7    age := 28
8    height := 1.65
9    city := "Guadalajara"
10    isStudent := false
11
12    fmt.Printf("=== Personal Profile ===\n")
13    fmt.Printf("Name:       %s\n", name)
14    fmt.Printf("Age:        %d years\n", age)
15    fmt.Printf("Height:     %.2f m\n", height)
16    fmt.Printf("City:       %s\n", city)
17    fmt.Printf("Student:    %t\n", isStudent)
18}

Exercise 2: Area Calculator

Calculate the area of a circle given its radius, using a constant for Pi:

go
1package main
2
3import "fmt"
4
5func main() {
6    const pi = 3.14159265358979
7    radius := 5.0
8
9    area := pi * radius * radius
10    perimeter := 2 * pi * radius
11
12    fmt.Printf("Radius: %.1f\n", radius)
13    fmt.Printf("Area: %.2f\n", area)
14    fmt.Printf("Perimeter: %.2f\n", perimeter)
15}

Exercise 3: Temperature Conversion

Convert a temperature from Celsius to Fahrenheit and Kelvin:

go
1package main
2
3import "fmt"
4
5func main() {
6    celsius := 37.0
7    fahrenheit := (celsius * 9.0 / 5.0) + 32.0
8    kelvin := celsius + 273.15
9
10    fmt.Printf("%.1f C = %.1f F = %.2f K\n", celsius, fahrenheit, kelvin)
11}

You now have a solid understanding of data types, variables, and constants in Go. These are the building blocks you will use in every program you write. In the next article (Part 3 of 10), we will learn about control structures: if statements, switch, and for loops, which will allow you to add logic and repetition to your programs.

Share:
CV

Cristhian Villegas

Software Engineer specializing in Java, Spring Boot, Angular & AWS. Building scalable distributed systems with clean architecture.

Comments

Sign in to leave a comment

No comments yet. Be the first!

Related Articles