Go Course #2: Variables, Data Types and Constants in Go
Introduction: Variables and Types in Go - Part 2 of 10

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.
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
| Type | Size | Range |
|---|---|---|
int | 32 or 64 bits (platform dependent) | Signed integer |
int8 | 8 bits | -128 to 127 |
int16 | 16 bits | -32768 to 32767 |
int32 | 32 bits | -2 billion to 2 billion |
int64 | 64 bits | Very large range |
uint | 32 or 64 bits | Positive numbers only |
Floating-Point Numeric Types
| Type | Precision |
|---|---|
float32 | Single precision (7 digits) |
float64 | Double precision (15 digits) - most commonly used |
Other Fundamental Types
string: Text string (immutable in Go)bool: Boolean value (trueorfalse)byte: Alias foruint8, used for binary datarune: Alias forint32, represents a Unicode character
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}
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)
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:
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}
:= 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
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.

| Type | Zero Value |
|---|---|
int, float64 | 0 |
string | "" (empty string) |
bool | false |
| Pointers, slices, maps | nil |
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}
Type Inference
When you use := or var without an explicit type, Go infers the type based on the assigned value:
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.
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:
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:
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}
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:
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}
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
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
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:
| Verb | Description | Example |
|---|---|---|
%d | Decimal integer | fmt.Printf("%d", 42) -> 42 |
%f | Floating point | fmt.Printf("%.2f", 3.14159) -> 3.14 |
%s | String | fmt.Printf("%s", "Go") -> Go |
%t | Boolean | fmt.Printf("%t", true) -> true |
%T | Type of the variable | fmt.Printf("%T", 42) -> int |
%v | Default value | fmt.Printf("%v", something) |
%+v | Value with field names | Useful for structs |
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}
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.
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:
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:
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.
Comments
Sign in to leave a comment
No comments yet. Be the first!