When AI generates Go code, variable declarations are in every function. You need to read them fluently, spot the declaration style, know the type, predict the zero value, and catch conversion mistakes. This lesson covers the patterns AI produces and the mistakes it makes.
Two ways to declare variables
AI will generate both styles. Knowing when each is appropriate helps you evaluate whether the AI made a good choice.
var, the explicit form
var name string
var age int
var isActive boolType comes after the name, opposite of C, Java, and TypeScript. Go's designers chose this order so variable names line up on the left when scanning a list.
You can declare and initialize together:
var name string = "Alice"
var age int = 30Or let Go infer the type from the value:
var name = "Alice" // inferred as string
var age = 30 // inferred as intShort declaration, the concise form
Inside functions, there's a shorter syntax:
name := "Alice"
age := 30
pi := 3.14159The := operator declares the variable and infers its type. This is the most common style in Go functions.
But := only works inside functions. At package level, you must use var:
package main
var globalName = "Alice" // Works
// globalName := "Alice" // Compile error - := not allowed here
func main() {
localName := "Bob" // Works - inside a function
}:= when it should use =. If a variable already exists, := creates a new variable that shadows the outer one. This is a common source of bugs:> err := firstOperation()
> if err != nil { return err }
> err := secondOperation() // COMPILE ERROR: no new variables on left side
> err = secondOperation() // CORRECT: reassignment with =
>The fix is
= for reassignment, := only for first declaration.| Situation | Use var | Use := |
|---|---|---|
| Package-level variable | Yes (required) | No (not allowed) |
| Need explicit type | var x int64 = 10 | No, := infers type |
| Zero-value initialization | var count int | No, := needs a value |
| Inside a function with value | Either works | Preferred, shorter |
| Reassigning existing variable | Use = | Use = (not :=) |
Go's type system
Go is statically typed, the compilerWhat is compiler?A program that translates code you write into a language your computer can execute. It also catches errors before your code runs. checks types before your code runs. AI-generated Go gets type-checked at compile time, catching mismatches that would be runtimeWhat is runtime?The environment that runs your code after it's written. Some languages need a runtime installed on the machine; others (like Go) bake it into the binary. errors in Python or JavaScript.
| Type | What it holds | Zero value | Common use |
|---|---|---|---|
int | Whole numbers (platform-sized) | 0 | Counters, indices |
int64 | 64-bit integers | 0 | Timestamps, large counts |
float64 | Decimal numbers | 0.0 | Math, measurements |
string | UTF-8 text (immutable) | "" | All text |
bool | true/false | false | Flags, conditions |
byte | Alias for uint8 | 0 | Raw data |
rune | Alias for int32 | 0 | Unicode code points |
For most code, int for whole numbers and float64 for decimals. You only need sized types (int32, int64) when interfacing with specific APIs or optimizing memory.
int when the API requires int64 (or vice versa). Go doesn't implicitly convert between integer sizes. If a function signature says func Process(id int64) and AI passes an int, the code won't compile. Watch for this at function call boundaries.Strings
Strings in Go are immutable byte sequences, UTF-8 by default:
name := "Alice"
greeting := "Hello, " + name // Concatenation creates a new string
message := "Hello, δΈη! π―π΅" // UTF-8 works out of the box+ allocates a new string. AI should use strings.Builder for building strings iteratively. If you see result += chunk inside a loop in AI output, flag it.Zero values: Go's "no magic" principle
Every variable in Go has a predictable default value. No undefined, no null that behaves differently depending on context, no uninitialized memory.
var count int // 0
var name string // "" (empty string)
var isReady bool // false
var data []byte // nil| Type category | Zero value |
|---|---|
| Integers | 0 |
| Floats | 0.0 |
| Strings | "" |
| Booleans | false |
| Pointers, slices, maps, channels | nil |
This matters when reading AI-generated code because AI sometimes explicitly initializes variables to their zero values, that's redundant:
var count int = 0 // Redundant - int is already 0
var name string = "" // Redundant - string is already ""
var count int // Idiomatic - zero value is implicit
var name string // Idiomaticvar m map[string]int and then tries to write to it, that's a nil map, it'll panic at runtime. A nil map can be read but not written to. The fix is m := make(map[string]int). This is one of Go's most common gotchas and AI hits it regularly.Type conversion: explicit only
Go refuses to convert types silently. You must state every conversion:
var i int = 42
var f float64 = float64(i) // Explicit - required
var u uint = uint(i) // Explicit - required
// This won't compile:
// var f float64 = i // ERROR: cannot use int as float64This prevents subtle bugs. In languages with implicit conversions, an int silently becoming a float64 might lose precision without you noticing.
String-to-number conversions
These use the strconv package and return errors (because parsing can fail):
import "strconv"
i, err := strconv.Atoi("42") // string β int
if err != nil {
// handle: "42abc" would fail here
}
s := strconv.Itoa(42) // int β string: "42"
f, err := strconv.ParseFloat("3.14", 64) // string β float64Notice the error return. Go makes failure explicit, AI-generated code that ignores these errors is a red flag.
int() does not convert strings to numbers. int("42") is a compile error. You need strconv.Atoi. AI trained on Python (where int("42") works) gets this wrong sometimes.Constants
Values that never change use const:
const Pi = 3.14159
const MaxRetries = 3
const AppName = "MyApp"Go constants can be untyped, which gives them flexibility:
const BigNumber = 1000000 // Untyped - adapts to context
var i int = BigNumber // Works as int
var f float64 = BigNumber // Works as float64Grouped constants with iota auto-increment:
const (
Low = iota // 0
Medium // 1
High // 2
)iota for constants whose values matter externally (API status codes, database enum values). If you insert a new constant in the middle, all values below it shift. For external-facing values, set them explicitly: const StatusActive = 1. Use iota only for internal enumerations where the actual number doesn't matter.The blank identifier
When a function returns multiple values and you don't need all of them, use _:
first, _ := GetName() // Discard second return value
_, err := DoSomething() // Only care about the errorGo requires you to use every declared variable. The blank identifier says "I'm intentionally ignoring this." Without it, unused variables cause compile errors.
Putting it together
When AI generates a function with variables, you should be able to read it like this:
func processUser(input string) (string, error) {
age, err := strconv.Atoi(input) // short decl, two returns
if err != nil {
return "", err // zero value string + error
}
var category string // zero value: ""
if age >= 18 {
category = "adult" // reassignment with =
}
ageFloat := float64(age) // explicit conversion
_ = ageFloat // suppress unused warning (bad practice)
return category, nil // nil means "no error"
}Every line uses patterns from this lesson: short declarations, explicit conversion, zero values, error returns, blank identifier. Fluency with these patterns means you can review AI-generated Go quickly and confidently.