Skip to main content

Variables, Types, & I/O

If variables are the building blocks of a programming language, then understanding how to declare them, what types they hold, and how to communicate with them (I/O) is mastering the DNA of your Go program.

Go has a specific philosophy regarding these fundamentals—it favors explicit control and strong typing, which helps build robust and efficient applications. This guide covers variables, basic data types, explicit type conversion, and the indispensable fmt package.


1. Variable Declaration: The Go Way

Go offers two primary methods for declaring variables, each suited for different contexts.

Method 1: The Explicit var Keyword

The var keyword is the classic way to declare a variable. It is mandatory when declaring variables outside of a function (package level) or when you want to explicitly declare a variable without immediately assigning a value.

Syntax Examples:

// Declaration without initialization (uses zero value)
var count int

// Declaration with type and initialization
var website string = "godev.blog"

// Declaration with initialization, letting Go infer the type
var isLearning = true

Insight: When using var name = value, Go automatically infers the data type based on the value assigned. This is called Type Inference.

Method 2: The Short Declaration Operator (:=)

The short declaration operator (:=) is the most idiomatic and frequently used method inside Go functions. It declares and initializes a variable in one quick step.

Key Rule: It must be used inside a function body.

func main() {
// Declares 'age' as an int
age := 30

// Declares 'price' as a float64
price := 99.99

// You must assign a value when using :=
message := "Hello Go!"
}
  • Use := inside functions for quick assignments.
  • Use var for global variables or when you need a specific type without an initial value.

2. Go's Basic Data Types

Go is a statically typed language, meaning every variable must have a defined type.

Core Types

  • Integers (int, int8, uint, etc.): Used for whole numbers. The plain int is generally sufficient, as it defaults to the most efficient size for your system (32 or 64 bits).
  • Floating-Point (float32, float64): Used for decimal numbers. float64 provides higher precision and is the default inference for decimals.
  • Strings (string): Immutable sequences of bytes (UTF-8 encoded).
  • Booleans (bool): Holds only true or false.

Go's Zero Values

A unique feature of Go is its concept of Zero Values. If you declare a variable using var but do not initialize it, Go guarantees it will have a predictable default value:

  • int, float: 0 or 0.0
  • bool: false
  • string: "" (the empty string)
var defaultAge int    // defaultAge is 0
var isActive bool // isActive is false

3. Handling Data Flow: Type Conversion

Unlike languages like JavaScript or Python, Go is extremely strict: it will never implicitly convert types for you (e.g., converting an int to a float).

The Conversion Syntax

To convert one type (T1) to another type (T2), you use the function-like syntax: T2(T1_variable).

package main

import "fmt"

func main() {
annualSalary := 50000
taxRate := 0.20 // This is a float64

// ERROR: Cannot multiply int and float64 directly
// totalTax := annualSalary * taxRate

// SOLUTION: Convert annualSalary to float64
totalTax := float64(annualSalary) * taxRate

fmt.Println("Total Tax:", totalTax)

// Converting float back to int (truncation occurs)
truncatedTax := int(totalTax)
fmt.Println("Truncated Tax:", truncatedTax)
}

4. Essential I/O with the fmt Package

The standard library's fmt package (Format) is how Go handles basic input and output.

A. Displaying Output: fmt.Println

The simplest way to print data. It prints arguments separated by spaces and adds a newline.

fmt.Println("The total is:", 100)
// Output: The total is: 100

B. Displaying Formatted Output: fmt.Printf

fmt.Printf allows you to control exactly how data is displayed using formatting verbs.

name := "Alice"
score := 95.5
fmt.Printf("%s scored %.1f points.\n", name, score)
// Output: Alice scored 95.5 points.

Common Formatting Verbs:

VerbDescriptionExample Output
%vValue in default format (simplest).fmt.Printf("%v", 100) -> 100
%TType of the value (good for debugging).fmt.Printf("%T", "hi") -> string
%dDecimal integer.fmt.Printf("%d", 42) -> 42
%sString.fmt.Printf("%s", "Go") -> Go
%fFloating point number.fmt.Printf("%.2f", 3.14) -> 3.14

C. Reading User Input: fmt.Scanln

To make your program interactive, fmt.Scanln reads space-separated values from standard input. It returns the number of items scanned and an error object.

package main

import "fmt"

func main() {
var username string
var favoriteNumber int

// 1. Prompt for input
fmt.Print("Enter your name: ")

// 2. Read input into the variable
// Note the '&' (address-of operator)
_, err := fmt.Scanln(&username)

// Basic error handling
if err != nil {
fmt.Println("Error reading name:", err)
return
}

fmt.Print("Enter your favorite number: ")
_, err = fmt.Scanln(&favoriteNumber)

if err != nil {
fmt.Println("Invalid number input.")
return
}

fmt.Printf("Hello, %s! Your lucky number is %d.\n", username, favoriteNumber)
}

The Ampersand (&): Notice the &username in the Scanln call. This is the address-of operator. Scanln needs the memory address of the variable so it can directly change the value stored there.


Conclusion

Mastering variable declaration (var vs. :=), understanding the default behavior of basic types, and using the fmt package are the essential first steps in your Go journey. Because Go is strongly typed, you write code that is safer and easier to debug right from the start.