Go Version Formats Supported by the internal/goversion Module
The internal/goversion module accepts Go version strings in multiple formats—including bare versions (1.24), prefixed versions (go1.24), patch versions (1.24.3), and development builds (devel)—and normalizes them to a standard major.minor form.
The internal/goversion package in the JetBrains/go-modern-guidelines repository provides robust parsing logic for Go toolchain version strings. Understanding what Go version formats this module supports is essential for developers working with Go version constraints and compatibility checks.
How the Parser Processes Version Strings
In internal/goversion/goversion.go, the normalizeGoVersion function implements a four-step pipeline to handle various Go version formats. This pipeline extracts numeric version components while discarding prefixes and patch levels. The implementation ensures consistent major.minor output regardless of input variations.
Step 1: Development Build Detection
The parser first checks for development builds using case-insensitive string comparison. According to the source code at lines 75–78, any string equal to "devel" (regardless of case) is mapped to a caller-provided development version parameter:
if strings.EqualFold(trimmed, "devel") {
// Maps to develVersion parameter
}
Step 2: Regex Pattern Matching
For non-development strings, the module applies a regular expression defined at line 16:
goVersionInText = regexp.MustCompile(`(?i)(?:^|\s)(?:go)?(\d+\.\d+)`)
This pattern matches an optional go prefix and optional leading whitespace, capturing only the major.minor component from inputs like "go1.24" or " go1.24.3".
Step 3: Major-Minor Extraction
The parseMajorMinor function, located at lines 96–102, splits the captured string on the period character using strings.Cut. It explicitly discards any patch-level version information by cutting the minor part at the first dot:
majorPart, minorPart, ok := strings.Cut(version, ".")
minorPart, _, _ = strings.Cut(minorPart, ".")
Step 4: Normalization Output
Finally, the parser formats the result at lines 88–89 using fmt.Sprintf. This produces the canonical major.minor string representation used throughout the package:
return fmt.Sprintf("%d.%d", majorMinor.major, majorMinor.minor)
Accepted Input Formats
Based on the parsing logic in internal/goversion/goversion.go, the module accepts six distinct categories of Go version formats. The following table illustrates how each input variant transforms during normalization.
| Input Example | Normalized Output | Notes |
|---|---|---|
1.24 |
1.24 |
Direct bare version |
go1.24 |
1.24 |
Prefix stripped automatically |
1.24.3 |
1.24 |
Patch component ignored |
go1.24.3 |
1.24 |
Both prefix and patch removed |
devel |
User-defined | Case-insensitive; uses develVersion parameter |
go version go1.24.5 linux/amd64 |
1.24 |
Extracted from full command output |
Error Handling for Invalid Formats
If a string does not contain a valid major.minor pattern, the normalizeGoVersion function returns a parsing error. Inputs such as "go1", "latest", or "1" lack the required dot-separated numeric components and trigger the error message: "cannot parse Go version …". This strict validation ensures type safety downstream in version comparison operations.
Practical Implementation Examples
The following example demonstrates how to use the Resolve and Compare functions from the internal/goversion module. These functions leverage the normalization pipeline to handle various input formats consistently.
package main
import (
"fmt"
"github.com/JetBrains/go-modern-guidelines/internal/goversion"
)
func main() {
// Example 1 – explicit version strings
for _, v := range []string{
"1.24", "go1.24", "1.24.5", "go1.24.3", "devel",
} {
norm, err := goversion.Resolve("", v, "1.23") // develVersion = "1.23"
if err != nil {
panic(err)
}
fmt.Printf("%s → %s\n", v, norm)
}
// Output:
// 1.24 → 1.24
// go1.24 → 1.24
// 1.24.5 → 1.24
// go1.24.3 → 1.24
// devel → 1.23
// Example 2 – comparing two version strings
fmt.Println("Compare 1.24 vs 1.23:", goversion.Compare("1.24", "1.23")) // >0
fmt.Println("Compare devel vs 1.24:", goversion.Compare("devel", "1.24")) // lexical compare
}
The test suite in internal/goversion/goversion_test.go provides additional examples of edge cases and validation scenarios.
Summary
- The
internal/goversionmodule normalizes all valid inputs tomajor.minorformat (e.g.,1.24) - Accepted formats include bare versions,
go-prefixed strings, patch versions (patch ignored), and case-insensitivedevelstrings - Rejected formats include incomplete versions like
"go1"or tags like"latest" - The parser uses a regex pattern
(?i)(?:^|\s)(?:go)?(\d+\.\d+)to extract version numbers from complex strings - Source files:
internal/goversion/goversion.go(implementation) andinternal/goversion/goversion_test.go(tests)
Frequently Asked Questions
Does internal/goversion support semantic versioning with patch numbers?
Yes, but patch numbers are discarded during normalization. When you provide a string like 1.24.3 or go1.24.5, the parseMajorMinor function extracts only the major and minor components, returning 1.24. The patch version does not affect the comparison logic or normalized output.
How does the module handle development builds of Go?
The module treats the string devel (case-insensitive) as a special identifier. When strings.EqualFold detects this value, the parser substitutes the caller-provided develVersion parameter instead of parsing the string numerically. This allows development builds to map to a specific comparable version number in your toolchain logic.
What happens when I pass an invalid version string like "latest"?
The normalizeGoVersion function returns a parsing error stating "cannot parse Go version …" because "latest" does not match the required major.minor pattern. The regex requires at least two numeric components separated by a dot, so single-component strings or non-numeric tags always fail validation.
Can the parser extract versions from full go version command output?
Yes. The regex pattern includes (?:^|\s) to match start-of-line or whitespace, allowing it to locate version strings within longer text such as go version go1.24.5 linux/amd64. The parser extracts the 1.24 component and ignores surrounding text, operating system identifiers, and architecture strings. This makes the module robust against raw command output parsing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →