1. go
  2. /basics
  3. /variables

Understanding Variables and Data Types in Go

Variables are fundamental building blocks in Go programming. This guide covers everything you need to know about declaring, initializing, and working with variables in Go.

Variable Declaration

Go provides several ways to declare variables:

1. Basic Declaration

var name string        // Declares a string variable
var age int           // Declares an integer variable
var isActive bool     // Declares a boolean variable

2. Declaration with Initialization

var name string = "Go"    // Declare and initialize
var age = 42             // Type inferred from value
var isActive = true      // Boolean type inferred

3. Short Declaration

name := "Go"             // Declare and initialize
age := 42                // Type inferred
isActive := true         // Most common in function bodies

4. Multiple Declarations

var (
    name     string = "Go"
    age      int    = 42
    isActive bool   = true
)

// Short declaration
name, age := "Go", 42

Basic Types

Go has several basic types:

1. Numeric Types

// Integers
var (
    a int     = 42    // Platform dependent (32 or 64 bit)
    b int8    = 127   // -128 to 127
    c int16   = 32767 // -32768 to 32767
    d int32   = 2147483647
    e int64   = 9223372036854775807
)

// Unsigned integers
var (
    f uint    = 42    // Platform dependent
    g uint8   = 255   // 0 to 255
    h uint16  = 65535 // 0 to 65535
    i uint32  = 4294967295
    j uint64  = 18446744073709551615
)

// Floating point
var (
    k float32 = 3.14  // Single precision
    l float64 = 3.14159265359  // Double precision
)

// Complex numbers
var (
    m complex64  = 1 + 2i
    n complex128 = 1.1 + 2.2i
)

2. String Type

var (
    name     = "Go"
    multiLine = `This is a
                 multi-line
                 string`
)

// String operations
length := len(name)
char := name[0]        // Get byte at index
slice := name[0:2]     // Substring

3. Boolean Type

var (
    isTrue  = true
    isFalse = false
)

// Boolean operations
result := isTrue && isFalse  // Logical AND
result = isTrue || isFalse   // Logical OR
result = !isTrue            // Logical NOT

Zero Values

Variables declared without initialization get zero values:

var (
    intZero     int     // 0
    floatZero   float64 // 0.0
    boolZero    bool    // false
    stringZero  string  // ""
    pointerZero *int    // nil
)

Type Conversion

Go requires explicit type conversion:

var (
    i int     = 42
    f float64 = float64(i)    // int to float64
    u uint    = uint(f)       // float64 to uint
)

// String conversions
import "strconv"

s1 := strconv.Itoa(i)        // Int to string
s2 := strconv.FormatFloat(f, 'f', 2, 64)  // Float to string
i2, err := strconv.Atoi("42")  // String to int
f2, err := strconv.ParseFloat("3.14", 64)  // String to float

Constants

Constants are declared using the const keyword:

const (
    Pi          = 3.14159
    StatusOK    = 200
    MaxUsers    = 1000
    ServerName  = "go-server"
)

// iota for enumerated constants
const (
    Sunday = iota    // 0
    Monday          // 1
    Tuesday         // 2
    Wednesday       // 3
    Thursday        // 4
    Friday         // 5
    Saturday        // 6
)

Variable Scope

1. Package Level

package main

var globalVar = "I'm global"  // Package level

func main() {
    println(globalVar)        // Accessible
}

func other() {
    println(globalVar)        // Also accessible
}

2. Function Level

func main() {
    localVar := "I'm local"   // Function level
    
    if true {
        blockVar := "I'm in a block"  // Block level
        println(localVar)     // Accessible
        println(blockVar)     // Accessible
    }
    
    println(localVar)         // Accessible
    // println(blockVar)      // Not accessible (out of scope)
}

Best Practices

1. Variable Naming

// Good names
var (
    userID      string
    firstName   string
    isValid     bool
    maxRetries  int
)

// Avoid
var (
    u          string  // Too short
    firstName1 string  // Numbered variables
    data       string  // Too vague
)

2. Short vs. Regular Declaration

// Use var for package level
var maxConnections = 100

func main() {
    // Use := for local variables
    count := 0
    
    // Use var when zero value is desired
    var buffer []byte
    
    // Use var for clarity with types
    var client *http.Client
}

3. Grouped Declarations

// Group related variables
var (
    // Server configuration
    host = "localhost"
    port = 8080
    
    // Database configuration
    dbUser = "admin"
    dbPass = "secret"
)

Common Patterns

1. Error Checking

if value, err := strconv.Atoi("42"); err != nil {
    // Handle error
    log.Printf("conversion failed: %v", err)
} else {
    // Use value
    fmt.Printf("converted value: %d", value)
}

2. Multiple Return Values

func divide(x, y float64) (float64, error) {
    if y == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return x / y, nil
}

result, err := divide(10, 2)

3. Blank Identifier

// Ignore unwanted values
_, err := someFunction()

// Import for side effects
import _ "github.com/lib/pq"

Common Mistakes

1. Shadowing Variables

var err error = errors.New("initial error")

func main() {
    // Wrong: shadows package level err
    if err := someFunction(); err != nil {
        log.Fatal(err)  // Only sees local err
    }
    
    // Right: use different name or existing variable
    if err2 := someFunction(); err2 != nil {
        log.Fatal(err2)
    }
}

2. Unused Variables

func main() {
    // Compile error: unused variable
    x := 42
    
    // Fix: use the variable or remove it
    x := 42
    fmt.Println(x)
}

Next Steps

  1. Learn about control structures
  2. Explore functions
  3. Study error handling
  4. Practice with data types

Additional Resources