Question
How can you specify the maximum value representable by an unsigned integer type in Go?
For example, suppose you want to initialize minLen before a loop that computes the minimum and maximum n values from a slice of structs:
var minLen uint = ???
var maxLen uint = 0
for _, thing := range sliceOfThings {
if minLen > thing.n {
minLen = thing.n
}
if maxLen < thing.n {
maxLen = thing.n
}
}
if minLen > maxLen {
// If there are no values, clamp min at 0 so that min <= max.
minLen = 0
}
What should minLen be initialized to so that, on the first comparison, minLen >= thing.n is true for any valid uint value?
Short Answer
By the end of this page, you will understand how Go represents the maximum value of unsigned integers, how to initialize a variable for minimum-value calculations, and safer alternatives for finding min and max values in loops.
Concept
In Go, unsigned integer types such as uint, uint8, uint16, uint32, and uint64 can only store non-negative values. Each type has a maximum representable value.
When computing a minimum value in a loop, a common technique is to initialize the min variable to the largest possible value for that type. That way, the first real value seen in the loop will always be smaller or equal, so it replaces the initial value.
For uint, the maximum value depends on the platform:
- On a 32-bit system,
uintis usually 32 bits. - On a 64-bit system,
uintis usually 64 bits.
So the maximum uint value is not a fixed number in source code unless you use a specific type like uint32 or uint64.
In Go, a classic way to get the maximum value of uint is:
^uint(0)
Why this works:
uint(0)is the value as a .
Mental Model
Think of minLen as starting with a value so large that any real measurement will be smaller.
Imagine you are trying to find the shortest rope in a pile.
- If you start with
minLen = 0, no rope will be shorter than that, so your minimum never updates. - If you start with an impossibly huge value, the first rope you inspect becomes the new minimum.
For uint, ^uint(0) is that “largest possible measuring stick.” It guarantees that the first real uint value you compare against will fit under it.
Syntax and Examples
To get the maximum value of uint, use:
maxUint := ^uint(0)
You can then use it to initialize a minimum:
var minLen uint = ^uint(0)
var maxLen uint = 0
for _, thing := range sliceOfThings {
if minLen > thing.n {
minLen = thing.n
}
if maxLen < thing.n {
maxLen = thing.n
}
}
if minLen > maxLen {
minLen = 0
}
Example with a complete program
package main
import "fmt"
type Thing struct {
n uint
}
func main() {
sliceOfThings := []Thing{{n: 8}, {n: 3}, {n: 12}, {n: 5}}
minLen := ^uint(0)
var maxLen uint =
_, thing := sliceOfThings {
minLen > thing.n {
minLen = thing.n
}
maxLen < thing.n {
maxLen = thing.n
}
}
minLen > maxLen {
minLen =
}
fmt.Println(, minLen)
fmt.Println(, maxLen)
}
Step by Step Execution
Consider this input:
sliceOfThings := []Thing{{n: 7}, {n: 2}, {n: 9}}
And this code:
minLen := ^uint(0)
var maxLen uint = 0
for _, thing := range sliceOfThings {
if minLen > thing.n {
minLen = thing.n
}
if maxLen < thing.n {
maxLen = thing.n
}
}
Step 1: Initial values
minLen = ^uint(0)→ maximum possibleuintmaxLen = 0
So before the loop:
minLenis very largemaxLenis very small for an unsigned type
Step 2: First iteration (thing.n = 7)
Check minimum:
if minLen > 7
This is true, because started at the maximum value.
Real World Use Cases
Finding minimum and maximum values appears often in real Go programs.
Data analysis
You may scan values to find:
- shortest and longest username lengths
- minimum and maximum order quantities
- smallest and largest response times
File and text processing
You might calculate:
- smallest and largest line lengths in a file
- shortest and longest filenames
- min/max token sizes in parsed text
APIs and services
A backend service may track:
- minimum and maximum request payload sizes
- smallest and largest batch sizes
- shortest and longest processing durations after converting to integer units
Monitoring and metrics
Metrics collectors often compute:
- min/max latency
- min/max queue depth
- min/max active connections
In all of these, correct initialization is important so the first real value updates the result properly.
Real Codebase Usage
In real codebases, developers usually use one of these patterns.
1. Sentinel initialization
This is the pattern from the question:
minVal := ^uint(0)
var maxVal uint
This is compact and works well when the type is unsigned.
2. Initialize from the first element
This is often the clearest approach:
if len(values) == 0 {
return 0, 0
}
minVal, maxVal := values[0], values[0]
for _, v := range values[1:] {
if v < minVal {
minVal = v
}
if v > maxVal {
maxVal = v
}
}
This avoids special-case sentinel values and usually reads better.
3. Guard clauses for empty input
Real functions often return early when input is empty:
func minMax(values []uint) (uint, uint, bool) {
(values) == {
, ,
}
minVal, maxVal := values[], values[]
_, v := values[:] {
v < minVal {
minVal = v
}
v > maxVal {
maxVal = v
}
}
minVal, maxVal,
}
Common Mistakes
Mistake 1: Initializing minLen to 0
This is the most common bug.
var minLen uint = 0
Problem:
- No
uintvalue is less than0 - So
minLennever updates unless the data contains0
Broken example:
values := []uint{5, 2, 8}
var min uint = 0
for _, v := range values {
if v < min {
min = v
}
}
fmt.Println(min) // wrong: 0
Use either:
min := ^uint(0)
or initialize from the first element.
Mistake 2: Confusing uint with
Comparisons
| Approach | Example | Good for | Drawbacks |
|---|---|---|---|
| Sentinel max value | min := ^uint(0) | Quick initialization for unsigned minimum search | Slightly less obvious to beginners |
| First-element initialization | min := values[0] | Clearer logic in many functions | Requires empty-slice check |
| Fixed-width maximum | min := ^uint32(0) | When working specifically with uint32 | Wrong if your values are plain uint |
uint vs int
| Type |
|---|
Cheat Sheet
Maximum unsigned integer values in Go
maxUint := ^uint(0)
maxUint8 := ^uint8(0)
maxUint16 := ^uint16(0)
maxUint32 := ^uint32(0)
maxUint64 := ^uint64(0)
Use it to initialize a minimum
min := ^uint(0)
Common min/max loop
min := ^uint(0)
var max uint = 0
for _, v := range values {
if v < min {
min = v
}
if v > max {
max = v
}
}
Empty slice handling
if min > max {
min = 0
}
Or better:
if len(values) == 0 {
return ,
}
FAQ
How do I get the maximum value of uint in Go?
Use:
^uint(0)
This flips all bits of zero, producing the largest possible uint value.
Why does ^uint(0) work?
Because 0 in binary is all zero bits. Applying bitwise NOT changes every bit to 1, which is the maximum unsigned value.
Is uint always 64-bit in Go?
No. uint is platform-dependent. It is typically 32 bits on 32-bit systems and 64 bits on 64-bit systems.
Should I use uint for all non-negative numbers?
Not necessarily. In Go, int is often preferred for general arithmetic. Use uint when the value is naturally unsigned and matches the API or domain.
What is the safest way to compute min and max in a slice?
A common safe approach is:
- check whether the slice is empty
- initialize
minand from the first element
Mini Project
Description
Build a small Go program that scans a slice of items and reports the minimum and maximum uint value found. This demonstrates how to initialize a minimum correctly, how to handle empty input, and how to write a reusable helper function.
Goal
Create a function that returns the minimum and maximum uint values from a slice, while safely handling the empty-slice case.
Requirements
- Create a
Thingstruct with an uintfield. - Write a function that accepts
[]Thingand returns min and max values. - Handle the case where the slice is empty.
- Use either
^uint(0)or first-element initialization correctly. - Print results for both a non-empty slice and an empty slice.
Keep learning
Related questions
Automatic Build Versioning in Go: Embed Incrementing Build Numbers
Learn how to add automatic build versioning in Go using linker flags, build metadata, CI counters, and Git-based version values.
Blank Identifier Imports in Go: What `_` Means in an Import Statement
Learn what `_` means in a Go import, why blank identifier imports run package init code, and when to use them safely.
Calling Functions Across Files in the Same Go Package
Learn how Go uses packages across multiple files, why functions may appear undefined, and how to organize code correctly.