# Go Version Formats Supported by the internal/goversion Module

> Discover the Go version formats supported by JetBrains go-modern-guidelines internal/goversion module. Handle bare, prefixed, patch, and devel versions.

- Repository: [JetBrains/go-modern-guidelines](https://github.com/jetbrains/go-modern-guidelines)
- Tags: api-reference
- Published: 2026-08-30

---

**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](https://github.com/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`](https://github.com/JetBrains/go-modern-guidelines/blob/main/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](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/goversion/goversion.go#L75-L78), any string equal to `"devel"` (regardless of case) is mapped to a caller-provided development version parameter:

```go
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](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/goversion/goversion.go#L16):

```go
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](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/goversion/goversion.go#L96-L102), 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:

```go
majorPart, minorPart, ok := strings.Cut(version, ".")
minorPart, _, _ = strings.Cut(minorPart, ".")

```

### Step 4: Normalization Output

Finally, the parser formats the result at [lines 88–89](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/goversion/goversion.go#L88-L89) using `fmt.Sprintf`. This produces the canonical `major.minor` string representation used throughout the package:

```go
return fmt.Sprintf("%d.%d", majorMinor.major, majorMinor.minor)

```

## Accepted Input Formats

Based on the parsing logic in [`internal/goversion/goversion.go`](https://github.com/JetBrains/go-modern-guidelines/blob/main/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.

```go
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`](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/goversion/goversion_test.go) provides additional examples of edge cases and validation scenarios.

## Summary

- The `internal/goversion` module normalizes all valid inputs to `major.minor` format (e.g., `1.24`)
- **Accepted formats** include bare versions, `go`-prefixed strings, patch versions (patch ignored), and case-insensitive `devel` strings
- **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`](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/goversion/goversion.go) (implementation) and [`internal/goversion/goversion_test.go`](https://github.com/JetBrains/go-modern-guidelines/blob/main/internal/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.