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
varfor 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 plainintis 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.float64provides higher precision and is the default inference for decimals. - Strings (
string): Immutable sequences of bytes (UTF-8 encoded). - Booleans (
bool): Holds onlytrueorfalse.
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:
0or0.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:
| Verb | Description | Example Output |
|---|---|---|
%v | Value in default format (simplest). | fmt.Printf("%v", 100) -> 100 |
%T | Type of the value (good for debugging). | fmt.Printf("%T", "hi") -> string |
%d | Decimal integer. | fmt.Printf("%d", 42) -> 42 |
%s | String. | fmt.Printf("%s", "Go") -> Go |
%f | Floating 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&usernamein theScanlncall. This is the address-of operator.Scanlnneeds 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.