chore: Enhance developer tooling and documentation

Adds `actionlint` to the pre-commit configuration to validate GitHub Actions workflows.

Significantly expands the `AGENTS.md` file with a comprehensive summary of new features and changes in Go 1.24 and 1.25, along with actionable recommendations for the project.

Additionally, normalizes markdown list formatting across various documentation files for consistency.
This commit is contained in:
2025-11-07 07:50:09 +01:00
parent 8d606706e2
commit a1a49a75b7
10 changed files with 672 additions and 279 deletions

View File

@ -22,7 +22,7 @@ jobs:
- name: Setup go deps - name: Setup go deps
run: | run: |
# Install golangci-lint # Install golangci-lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b "$(go env GOPATH)/bin"
# Install go-task dependencies # Install go-task dependencies
go install golang.org/x/tools/cmd/goimports@latest go install golang.org/x/tools/cmd/goimports@latest

View File

@ -67,13 +67,15 @@ jobs:
env: env:
CGO_ENABLED: 1 CGO_ENABLED: 1
run: | run: |
cat >> $GITHUB_STEP_SUMMARY << EOF {
cat << EOF
## 🔧 Test Environment ## 🔧 Test Environment
- **Go Version:** ${{ matrix.go }} - **Go Version:** ${{ matrix.go }}
- **OS:** ubuntu-latest - **OS:** ubuntu-latest
- **Timestamp:** $(date -u) - **Timestamp:** $(date -u)
EOF EOF
} >> "$GITHUB_STEP_SUMMARY"
echo "Running tests with coverage..." echo "Running tests with coverage..."
task test:coverage 2>&1 | tee test-output.log task test:coverage 2>&1 | tee test-output.log
@ -86,16 +88,17 @@ jobs:
SKIPPED_TESTS=$(grep -c -- "--- SKIP:" test-output.log || echo "0") SKIPPED_TESTS=$(grep -c -- "--- SKIP:" test-output.log || echo "0")
# Generate test summary # Generate test summary
cat >> $GITHUB_STEP_SUMMARY << EOF {
cat << EOF
## 🧪 Test Results (Go ${{ matrix.go }}) ## 🧪 Test Results (Go ${{ matrix.go }})
| Metric | Value | | Metric | Value |
| ----------- | ----------------------------------------------------------- | | ----------- | ------------------------------------------------------------- |
| Total Tests | $TOTAL_TESTS | | Total Tests | $TOTAL_TESTS |
| Passed | $PASSED_TESTS | | Passed | $PASSED_TESTS |
| Failed | $FAILED_TESTS | | Failed | $FAILED_TESTS |
| Skipped | $SKIPPED_TESTS | | Skipped | $SKIPPED_TESTS |
| Status | $([ $TEST_STATUS -eq 0 ] && echo "PASSED" || echo "FAILED") | | Status | $([ "$TEST_STATUS" -eq 0 ] && echo "PASSED" || echo "FAILED") |
### 📦 Package Test Results ### 📦 Package Test Results
@ -107,36 +110,39 @@ jobs:
grep "^ok\|^FAIL" test-output.log | while read -r line; do grep "^ok\|^FAIL" test-output.log | while read -r line; do
if [[ $line == ok* ]]; then if [[ $line == ok* ]]; then
pkg=$(echo "$line" | awk '{print $2}') pkg=$(echo "$line" | awk '{print $2}')
echo "| $pkg | ✅ PASS |" >> $GITHUB_STEP_SUMMARY echo "| $pkg | ✅ PASS |"
elif [[ $line == FAIL* ]]; then elif [[ $line == FAIL* ]]; then
pkg=$(echo "$line" | awk '{print $2}') pkg=$(echo "$line" | awk '{print $2}')
echo "| $pkg | ❌ FAIL |" >> $GITHUB_STEP_SUMMARY echo "| $pkg | ❌ FAIL |"
fi fi
done done
echo "" >> $GITHUB_STEP_SUMMARY echo ""
# Add detailed results if tests failed # Add detailed results if tests failed
if [ $TEST_STATUS -ne 0 ]; then if [ "$TEST_STATUS" -ne 0 ]; then
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat << 'EOF'
### ❌ Failed Tests Details ### ❌ Failed Tests Details
``` ```
EOF EOF
grep -A 10 -- "--- FAIL:" test-output.log | head -100 >> $GITHUB_STEP_SUMMARY grep -A 10 -- "--- FAIL:" test-output.log | head -100
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat << 'EOF'
``` ```
EOF EOF
fi fi
} >> "$GITHUB_STEP_SUMMARY"
# Set outputs for other steps # Set outputs for other steps
echo "test-status=$TEST_STATUS" >> $GITHUB_OUTPUT {
echo "total-tests=$TOTAL_TESTS" >> $GITHUB_OUTPUT echo "test-status=$TEST_STATUS"
echo "passed-tests=$PASSED_TESTS" >> $GITHUB_OUTPUT echo "total-tests=$TOTAL_TESTS"
echo "failed-tests=$FAILED_TESTS" >> $GITHUB_OUTPUT echo "passed-tests=$PASSED_TESTS"
echo "failed-tests=$FAILED_TESTS"
} >> "$GITHUB_OUTPUT"
# Exit with the original test status # Exit with the original test status
exit $TEST_STATUS exit "$TEST_STATUS"
- name: Generate coverage report - name: Generate coverage report
if: always() if: always()
@ -144,7 +150,8 @@ jobs:
if [ -f coverage/coverage.out ]; then if [ -f coverage/coverage.out ]; then
COVERAGE=$(go tool cover -func=coverage/coverage.out | grep total | awk '{print $3}') COVERAGE=$(go tool cover -func=coverage/coverage.out | grep total | awk '{print $3}')
cat >> $GITHUB_STEP_SUMMARY << EOF {
cat << EOF
## 📊 Code Coverage (Go ${{ matrix.go }}) ## 📊 Code Coverage (Go ${{ matrix.go }})
**Total Coverage: $COVERAGE** **Total Coverage: $COVERAGE**
@ -184,17 +191,18 @@ jobs:
avg = packages[pkg] / counts[pkg] avg = packages[pkg] / counts[pkg]
printf "| %s | %.1f%% |\n", pkg, avg printf "| %s | %.1f%% |\n", pkg, avg
} }
}' "$temp_coverage" | sort >> $GITHUB_STEP_SUMMARY }' "$temp_coverage" | sort
rm -f "$temp_coverage" rm -f "$temp_coverage"
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat << 'EOF'
</details> </details>
EOF EOF
} >> "$GITHUB_STEP_SUMMARY"
else else
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
## ⚠️ Coverage Report ## ⚠️ Coverage Report
No coverage file generated No coverage file generated
@ -214,7 +222,8 @@ jobs:
- name: Run linters - name: Run linters
run: | run: |
# Initialize summary # Initialize summary
cat >> $GITHUB_STEP_SUMMARY << EOF {
cat << EOF
## 🔍 Static Analysis (Go ${{ matrix.go }}) ## 🔍 Static Analysis (Go ${{ matrix.go }})
EOF EOF
@ -223,42 +232,43 @@ jobs:
VET_OUTPUT=$(task lint:vet 2>&1 || echo "") VET_OUTPUT=$(task lint:vet 2>&1 || echo "")
VET_STATUS=$? VET_STATUS=$?
if [ $VET_STATUS -eq 0 ]; then if [ "$VET_STATUS" -eq 0 ]; then
echo "✅ **go vet:** No issues found" >> $GITHUB_STEP_SUMMARY echo "✅ **go vet:** No issues found"
else else
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat << 'EOF'
❌ **go vet:** Issues found ❌ **go vet:** Issues found
``` ```
EOF EOF
echo "$VET_OUTPUT" >> $GITHUB_STEP_SUMMARY echo "$VET_OUTPUT"
echo '```' >> $GITHUB_STEP_SUMMARY echo '```'
fi fi
echo "" >> $GITHUB_STEP_SUMMARY echo ""
# Run go fmt check # Run go fmt check
FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "") FMT_OUTPUT=$(task lint:fmt 2>&1 || echo "")
FMT_STATUS=$? FMT_STATUS=$?
if [ $FMT_STATUS -eq 0 ]; then if [ "$FMT_STATUS" -eq 0 ]; then
echo "✅ **go fmt:** All files properly formatted" >> $GITHUB_STEP_SUMMARY echo "✅ **go fmt:** All files properly formatted"
else else
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat << 'EOF'
❌ **go fmt:** Files need formatting ❌ **go fmt:** Files need formatting
``` ```
EOF EOF
echo "$FMT_OUTPUT" >> $GITHUB_STEP_SUMMARY echo "$FMT_OUTPUT"
echo '```' >> $GITHUB_STEP_SUMMARY echo '```'
fi fi
} >> "$GITHUB_STEP_SUMMARY"
# Exit with error if any linter failed # Exit with error if any linter failed
[ $VET_STATUS -eq 0 ] && [ $FMT_STATUS -eq 0 ] || exit 1 [ "$VET_STATUS" -eq 0 ] && [ "$FMT_STATUS" -eq 0 ] || exit 1
- name: Job Summary - name: Job Summary
if: always() if: always()
run: | run: |
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
## 📋 Job Summary (Go ${{ matrix.go }}) ## 📋 Job Summary (Go ${{ matrix.go }})
| Step | Status | | Step | Status |
@ -313,7 +323,8 @@ jobs:
- name: Test Docker image using Task - name: Test Docker image using Task
run: | run: |
cat >> $GITHUB_STEP_SUMMARY << 'EOF' {
cat << 'EOF'
## 🧪 Docker Image Tests ## 🧪 Docker Image Tests
EOF EOF
@ -321,16 +332,17 @@ jobs:
# Run Task docker test # Run Task docker test
task docker:test task docker:test
echo "**Testing help command:**" >> $GITHUB_STEP_SUMMARY echo "**Testing help command:**"
echo '```terminaloutput' >> $GITHUB_STEP_SUMMARY echo '```terminaloutput'
docker run --rm articulate-parser:latest --help >> $GITHUB_STEP_SUMMARY docker run --rm articulate-parser:latest --help
echo '```' >> $GITHUB_STEP_SUMMARY echo '```'
echo "" >> $GITHUB_STEP_SUMMARY echo ""
# Test image size # Test image size
IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B) IMAGE_SIZE=$(docker image inspect articulate-parser:latest --format='{{.Size}}' | numfmt --to=iec-i --suffix=B)
echo "**Image size:** $IMAGE_SIZE" >> $GITHUB_STEP_SUMMARY echo "**Image size:** $IMAGE_SIZE"
echo "" >> $GITHUB_STEP_SUMMARY echo ""
} >> "$GITHUB_STEP_SUMMARY"
dependency-review: dependency-review:
name: Dependency Review name: Dependency Review
@ -433,7 +445,7 @@ jobs:
- name: Generate Docker summary - name: Generate Docker summary
run: | run: |
cat >> $GITHUB_STEP_SUMMARY << 'EOF' cat >> "$GITHUB_STEP_SUMMARY" << 'EOF'
## 🐳 Docker Build Summary ## 🐳 Docker Build Summary
**Image:** `ghcr.io/${{ github.repository }}` **Image:** `ghcr.io/${{ github.repository }}`

View File

@ -29,6 +29,16 @@ repos:
- id: check-added-large-files - id: check-added-large-files
- id: check-symlinks - id: check-symlinks
- id: check-executables-have-shebangs - id: check-executables-have-shebangs
- repo: local
hooks:
- id: actionlint
name: Lint GitHub Actions workflow files
description: Runs actionlint to lint GitHub Actions workflow files
language: golang
types: ["yaml"]
files: ^\.github/workflows/
entry: actionlint
minimum_pre_commit_version: 3.0.0
- repo: https://github.com/golangci/golangci-lint - repo: https://github.com/golangci/golangci-lint
rev: v2.6.1 rev: v2.6.1
hooks: hooks:

371
AGENTS.md
View File

@ -1,6 +1,7 @@
# Agent Guidelines for articulate-parser # Agent Guidelines for articulate-parser
## Build/Test Commands ## Build/Test Commands
- **Build**: `task build` or `go build -o bin/articulate-parser main.go` - **Build**: `task build` or `go build -o bin/articulate-parser main.go`
- **Run tests**: `task test` or `go test -race -timeout 5m ./...` - **Run tests**: `task test` or `go test -race -timeout 5m ./...`
- **Run single test**: `go test -v -race -run ^TestName$ ./path/to/package` - **Run single test**: `go test -v -race -run ^TestName$ ./path/to/package`
@ -14,43 +15,413 @@
## Code Style Guidelines ## Code Style Guidelines
### Imports ### Imports
- Use `goimports` with local prefix: `github.com/kjanat/articulate-parser` - Use `goimports` with local prefix: `github.com/kjanat/articulate-parser`
- Order: stdlib, external, internal packages - Order: stdlib, external, internal packages
- Group related imports together - Group related imports together
### Formatting ### Formatting
- Use `gofmt -s` (simplify) and `gofumpt` with extra rules - Use `gofmt -s` (simplify) and `gofumpt` with extra rules
- Function length: max 100 lines, 50 statements - Function length: max 100 lines, 50 statements
- Cyclomatic complexity: max 15 - Cyclomatic complexity: max 15
- Cognitive complexity: max 20 - Cognitive complexity: max 20
### Types & Naming ### Types & Naming
- Use interface-based design (see `internal/interfaces/`) - Use interface-based design (see `internal/interfaces/`)
- Export types/functions with clear godoc comments ending with period - Export types/functions with clear godoc comments ending with period
- Use descriptive names: `ArticulateParser`, `MarkdownExporter` - Use descriptive names: `ArticulateParser`, `MarkdownExporter`
- Receiver names: short (1-2 chars), consistent per type - Receiver names: short (1-2 chars), consistent per type
### Error Handling ### Error Handling
- Always wrap errors with context: `fmt.Errorf("operation failed: %w", err)` - Always wrap errors with context: `fmt.Errorf("operation failed: %w", err)`
- Use `%w` verb for error wrapping to preserve error chain - Use `%w` verb for error wrapping to preserve error chain
- Check all error returns (enforced by `errcheck`) - Check all error returns (enforced by `errcheck`)
- Document error handling rationale in defer blocks when ignoring close errors - Document error handling rationale in defer blocks when ignoring close errors
### Comments ### Comments
- All exported types/functions require godoc comments - All exported types/functions require godoc comments
- End sentences with periods (`godot` linter enforced) - End sentences with periods (`godot` linter enforced)
- Mark known issues with TODO/FIXME/HACK/BUG/XXX - Mark known issues with TODO/FIXME/HACK/BUG/XXX
### Security ### Security
- Use `#nosec` with justification for deliberate security exceptions (G304 for CLI file paths, G306 for export file permissions) - Use `#nosec` with justification for deliberate security exceptions (G304 for CLI file paths, G306 for export file permissions)
- Run `gosec` and `govulncheck` for security audits - Run `gosec` and `govulncheck` for security audits
### Testing ### Testing
- Enable race detection: `-race` flag - Enable race detection: `-race` flag
- Use table-driven tests where applicable - Use table-driven tests where applicable
- Mark test helpers with `t.Helper()` - Mark test helpers with `t.Helper()`
- Benchmarks in `*_bench_test.go`, examples in `*_example_test.go` - Benchmarks in `*_bench_test.go`, examples in `*_example_test.go`
### Dependencies ### Dependencies
- Minimal external dependencies (currently: go-docx, golang.org/x/net, golang.org/x/text) - Minimal external dependencies (currently: go-docx, golang.org/x/net, golang.org/x/text)
- Run `task deps:tidy` after adding/removing dependencies - Run `task deps:tidy` after adding/removing dependencies
---
## Go 1.24 & 1.25 New Features Reference
This project uses Go 1.24+. Below is a comprehensive summary of new features and changes in Go 1.24 and 1.25 that may be relevant for development and maintenance.
### Go 1.24 Major Changes (Released February 2025)
#### Language Features
**Generic Type Aliases**
- Type aliases can now be parameterized with type parameters
- Example: `type List[T any] = []T`
- Can be disabled via `GOEXPERIMENT=noaliastypeparams` (removed in 1.25)
#### Tooling Enhancements
**Module Tool Dependencies**
- New `tool` directive in go.mod tracks executable dependencies
- Use `go get -tool <package>` to add tool dependencies
- Use `go install tool` and `go get tool` to manage them
- Eliminates need for blank imports in `tools.go` files
**Build Output Formatting**
- Both `go build` and `go test` support `-json` flag for structured JSON output
- New action types distinguish build output from test results
**Authentication**
- New `GOAUTH` environment variable provides flexible authentication for private modules
**Automatic Version Tracking**
- `go build` automatically sets main module version in binaries based on VCS tags
- Adds `+dirty` suffix for uncommitted changes
**Cgo Performance Improvements**
- New `#cgo noescape` annotation: Prevents escape analysis overhead for C function calls
- New `#cgo nocallback` annotation: Indicates C function won't call back to Go
**Toolchain Tracing**
- `GODEBUG=toolchaintrace=1` enables tracing of toolchain selection
#### Runtime & Performance
**Performance Improvements**
- **2-3% CPU overhead reduction** across benchmark suites
- New Swiss Tables-based map implementation (faster lookups)
- Disable via `GOEXPERIMENT=noswissmap`
- More efficient small object allocation
- Redesigned runtime-internal mutexes
- Disable via `GOEXPERIMENT=nospinbitmutex`
#### Compiler & Linker
**Method Receiver Restrictions**
- Methods on cgo-generated types now prevented (both directly and through aliases)
**Build IDs**
- Linkers generate GNU build IDs (ELF) and UUIDs (macOS) by default
- Disable via `-B none` flag
#### Standard Library Additions
**File System Safety - `os.Root`**
- New `os.Root` type enables directory-limited operations
- Prevents path escape and symlink breakouts
- Essential for sandboxed file operations
**Cryptography Expansion**
- `crypto/mlkem`: ML-KEM-768/1024 post-quantum key exchange (FIPS 203)
- `crypto/hkdf`: HMAC-based Extract-and-Expand KDF (RFC 5869)
- `crypto/pbkdf2`: Password-based key derivation (RFC 8018)
- `crypto/sha3`: SHA-3 and SHAKE functions (FIPS 202)
**FIPS 140-3 Support**
- New `GOFIPS140` environment variable enables FIPS mode
- New `fips140` GODEBUG setting for cryptographic module compliance
**Weak References - `weak` Package**
- New `weak` package provides low-level weak pointers
- Enables memory-efficient structures like weak maps and caches
- Useful for preventing memory leaks in cache implementations
**Testing Improvements**
- `testing.B.Loop()`: Cleaner syntax replacing manual `b.N` iteration
- Prevents compiler from optimizing away benchmarked code
- New `testing/synctest` package (experimental) for testing concurrent code with fake clocks
**Iterator Support**
- Multiple packages now offer iterator-returning variants:
- `bytes`: Iterator-based functions
- `strings`: Iterator-based functions
- `go/types`: Iterator support
#### Security Enhancements
**TLS Post-Quantum Cryptography**
- `X25519MLKEM768` hybrid key exchange enabled by default in TLS
- Provides quantum-resistant security
**Encrypted Client Hello (ECH)**
- TLS servers can enable ECH via `Config.EncryptedClientHelloKeys`
- Protects client identity during TLS handshake
**RSA Key Validation**
- Keys smaller than 1024 bits now rejected by default
- Use `GODEBUG=rsa1024min=0` to revert (testing only)
**Constant-Time Execution**
- New `crypto/subtle.WithDataIndependentTiming()` enables architecture-specific timing guarantees
- Helps prevent timing attacks
#### Deprecations & Removals
- `runtime.GOROOT()`: Deprecated; use system path instead
- `crypto/cipher` OFB/CFB modes: Deprecated (unauthenticated encryption)
- `x509sha1` GODEBUG: Removed; SHA-1 certificates no longer verified
- Experimental `X25519Kyber768Draft00`: Removed
#### Platform Changes
- **Linux**: Now requires kernel 3.2+ (enforced)
- **macOS**: Go 1.24 is final release supporting Big Sur
- **Windows/ARM 32-bit**: Marked broken
- **WebAssembly**:
- New `go:wasmexport` directive
- Reactor/library builds supported via `-buildmode=c-shared`
#### Bootstrap Requirements
- Go 1.24 requires Go 1.22.6+ for bootstrapping
- Go 1.26 will require Go 1.24+
---
### Go 1.25 Major Changes (Released August 2025)
#### Language Changes
- No breaking language changes
- "Core types" concept removed from specification (replaced with clearer prose)
#### Tooling Improvements
**Go Command Enhancements**
- `go build -asan`: Now defaults to leak detection at program exit
- New `go.mod ignore` directive: Specify directories for go command to ignore
- `go doc -http`: Starts documentation server and opens in browser
- `go version -m -json`: Prints JSON-encoded BuildInfo structures
- Module path resolution now supports subdirectories using `<meta>` syntax
- New `work` package pattern matches all packages in work/workspace modules
- Removed automatic toolchain line additions when updating `go` version
**Vet Analyzers**
- **"waitgroup"**: Detects misplaced `sync.WaitGroup.Add` calls
- **"hostport"**: Warns against using `fmt.Sprintf` for constructing addresses
- Recommends `net.JoinHostPort` instead
#### Runtime Enhancements
**Container-Aware GOMAXPROCS**
- Linux now respects cgroup CPU bandwidth limits
- All OSes periodically update GOMAXPROCS if CPU availability changes
- Disable via environment variables or GODEBUG settings
- Critical for containerized applications
**New Garbage Collector - "Green Tea GC"**
- Experimental `GOEXPERIMENT=greenteagc` enables new GC
- **10-40% reduction in garbage collection overhead**
- Significant for GC-sensitive applications
**Trace Flight Recorder**
- New `runtime/trace.FlightRecorder` API
- Captures execution traces in in-memory ring buffer
- Essential for debugging rare events and production issues
**Other Runtime Changes**
- Simplified unhandled panic output
- VMA names on Linux identify memory purpose (debugging aid)
- New `SetDefaultGOMAXPROCS` function resets GOMAXPROCS to defaults
#### Compiler Fixes & Improvements
**Critical Nil Pointer Bug Fix**
- Fixed Go 1.21 regression where nil pointer checks were incorrectly delayed
- ⚠️ **May cause previously passing code to now panic** (correct behavior)
- Review code for assumptions about delayed nil checks
**DWARF5 Support**
- Debug information now uses DWARF version 5
- Reduces binary size and linking time
- Better debugging experience
**Faster Slices**
- Expanded stack allocation for slice backing stores
- Improved slice performance
#### Linker
- New `-funcalign=N` option specifies function entry alignment
#### Standard Library Highlights
**New Packages**
1. **`testing/synctest`** (Promoted from Experimental)
- Concurrent code testing with virtualized time
- Control time progression in tests
- Essential for testing time-dependent concurrent code
2. **`encoding/json/v2`** (Experimental)
- **Substantially better decoding performance**
- Improved API design
- Backward compatible with v1
**Major Package Updates**
| Package | Key Changes |
|---------|------------|
| `crypto` | New `MessageSigner` interface and `SignMessage` function |
| `crypto/ecdsa` | New raw key parsing/serialization functions |
| `crypto/rsa` | **Key generation now 3x faster** |
| `crypto/sha1` | **Hashing 2x faster on amd64 with SHA-NI** |
| `crypto/tls` | New `CurveID` field; SHA-1 algorithms disallowed in TLS 1.2 |
| `net` | Windows now supports file-to-connection conversion; IPv6 multicast improvements |
| `net/http` | **New `CrossOriginProtection` middleware for CSRF defense** |
| `os` | Windows async I/O support; `Root` type expanded with 12 new methods |
| `sync` | **New `WaitGroup.Go` method for convenient goroutine creation** |
| `testing` | New `Attr`, `Output` methods; `AllocsPerRun` panics with parallel tests |
| `unique` | More eager and parallel reclamation of interned values |
#### Performance Notes
**Performance Improvements**
- ECDSA and Ed25519 signing **4x faster** in FIPS 140-3 mode
- SHA3 hashing **2x faster** on Apple M processors
- AMD64 fused multiply-add instructions in v3+ mode
- ⚠️ **Changes floating-point results** (within IEEE 754 spec)
**Performance Regressions**
- SHA-1, SHA-256, SHA-512 slower without AVX2
- Most servers post-2015 support AVX2
#### Platform Changes
- **macOS**: Requires version 12 Monterey or later
- **Windows**: 32-bit windows/arm port marked for removal in Go 1.26
- **Loong64**: Race detector now supported
- **RISC-V**:
- Plugin build mode support
- New `GORISCV64=rva23u64` environment variable value
#### Deprecations
- `go/ast` functions: `FilterPackage`, `PackageExports`, `MergePackageFiles`
- `go/parser.ParseDir` function
- Old `testing/synctest` API (when `GOEXPERIMENT=synctest` set)
---
### Actionable Recommendations for This Project
#### Immediate Opportunities
1. **Replace `sync.WaitGroup` patterns with `WaitGroup.Go()`** (Go 1.25)
```go
// Old pattern
wg.Add(1)
go func() {
defer wg.Done()
// work
}()
// New pattern (Go 1.25)
wg.Go(func() {
// work
})
```
2. **Use `testing.B.Loop()` in benchmarks** (Go 1.24)
```go
// Old pattern
for i := 0; i < b.N; i++ {
// benchmark code
}
// New pattern (Go 1.24)
for b.Loop() {
// benchmark code
}
```
3. **Consider `os.Root` for file operations** (Go 1.24)
- Prevents path traversal vulnerabilities
- Safer for user-provided file paths
4. **Enable Green Tea GC for testing** (Go 1.25)
- Test with `GOEXPERIMENT=greenteagc`
- May reduce GC overhead by 10-40%
5. **Leverage container-aware GOMAXPROCS** (Go 1.25)
- No changes needed; automatic in containers
- Improves resource utilization
6. **Review floating-point operations** (Go 1.25)
- AMD64 v3+ uses FMA instructions
- May change floating-point results (within spec)
7. **Watch nil pointer checks** (Go 1.25)
- Compiler bug fix may expose latent nil pointer bugs
- Review crash reports carefully
#### Future Considerations
1. **Evaluate `encoding/json/v2`** when stable
- Better performance for JSON operations
- Currently experimental in Go 1.25
2. **Adopt tool directives** in go.mod
- Cleaner dependency management for build tools
- Remove `tools.go` if present
3. **Enable FIPS mode if required**
- Use `GOFIPS140=1` for compliance
- Performance improvements in Go 1.25 (4x faster signing)
4. **Use `runtime/trace.FlightRecorder`** for production debugging
- Capture traces of rare events
- Minimal overhead when not triggered