Go 1.25: Novità e Miglioramenti
Scopri Go 1.25: JSON v2, Green Tea GC, Container-aware GOMAXPROCS, testing/synctest, Core Types Removal e tutte le novità di agosto 2025.

Go 1.25 è stato rilasciato il 12 agosto 2025. Questa release introduce l'encoding/json/v2 sperimentale con performance 10x superiori, il nuovo Green Tea GC che riduce overhead del 10-40%, Container-aware GOMAXPROCS, testing/synctest stabile e rimuove il concetto di Core Types dalla spec.
🎯 Novità Principali
JSON v2 Package (Experimental) 🔥
La feature più attesa: nuova implementazione JSON con performance 10x superiori!
Abilita JSON v2:
# Build con JSON v2
GOEXPERIMENT=jsonv2 go build
# O set environment
export GOEXPERIMENT=jsonv2
go run main.go
✅ API retrocompatibile con v1:
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
user := User{ID: 1, Name: "Alice", Email: "alice@example.com"}
// ✅ Stesso API, performance 10x migliori!
data, err := json.Marshal(user)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}
Nuove feature JSON v2:
1. Streaming diretto:
import "encoding/json/v2"
// ✅ MarshalWrite - scrivi direttamente senza buffer
var buf bytes.Buffer
err := json.MarshalWrite(&buf, user)
// ✅ UnmarshalRead - leggi direttamente da reader
var decoded User
err := json.UnmarshalRead(resp.Body, &decoded)
2. jsontext package per streaming avanzato:
import "encoding/json/v2/jsontext"
// Encoder avanzato
enc := jsontext.NewEncoder(&buf)
enc.WriteToken(jsontext.ObjectStart)
enc.WriteToken(jsontext.String("name"))
enc.WriteToken(jsontext.String("Alice"))
enc.WriteToken(jsontext.ObjectEnd)
3. Opzioni di marshaling personalizzate:
import "encoding/json/v2"
// Configura comportamento nil slices
opts := json.MarshalOptions{
FormatNilSliceAsNull: false, // [] invece di null
}
data, err := json.MarshalWithOptions(users, opts)
4. Struct tag potenti:
type Product struct {
ID int `json:"id"`
Name string `json:"name,omitzero"` // Ometti se zero value
Price float64 `json:"price,string"` // Marshal come string
// ✨ Inline nested struct
Details Details `json:",inline"`
// ✨ Case-insensitive unmarshal
Category string `json:"category,nocase"`
}
5. Custom marshal/unmarshal più flessibile:
type Timestamp time.Time
func (t Timestamp) MarshalJSON() ([]byte, error) {
return []byte(`"` + time.Time(t).Format(time.RFC3339) + `"`), nil
}
func (t *Timestamp) UnmarshalJSON(data []byte) error {
s := string(data[1 : len(data)-1]) // Remove quotes
parsed, err := time.Parse(time.RFC3339, s)
if err != nil {
return err
}
*t = Timestamp(parsed)
return nil
}
Performance benchmarks JSON v2:
// Benchmark risultati
BenchmarkMarshal_v1 1000000 1200 ns/op 500 B/op
BenchmarkMarshal_v2 10000000 120 ns/op 48 B/op // 10x faster!
BenchmarkUnmarshal_v1 500000 2400 ns/op 800 B/op
BenchmarkUnmarshal_v2 5000000 280 ns/op 80 B/op // 8.5x faster!
Vantaggi JSON v2:
- ✅ 10x faster: Unmarshal drammaticamente più veloce
- ✅ Zero-alloc: Molti struct senza heap allocations
- ✅ Streaming: API diretta senza buffer intermedi
- ✅ Configurabile: Opzioni ricche per customize behavior
- ✅ Backward compatible: Drop-in replacement per v1
Green Tea GC (Experimental) 🍵
Nuovo garbage collector con 10-40% meno overhead!
Abilita Green Tea GC:
# Build con nuovo GC
GOEXPERIMENT=greenteagc go build
# O runtime flag
export GOEXPERIMENT=greenteagc
go run main.go
Come funziona:
Il Green Tea GC migliora:
- Locality: Oggetti piccoli scansionati più efficientemente
- Parallelism: Migliore utilizzo CPU durante mark phase
- Scanning: Algoritmo ottimizzato per small objects
Performance impact:
// Workload GC-intensive
type Node struct {
Value int
Next *Node
}
// Green Tea GC benefici:
// - Applicazioni con molti small objects: -20-40% GC overhead
// - Microservices con alta allocazione rate: -15-25% latency
// - Data processing pipelines: +10-20% throughput
Monitor GC performance:
import "runtime"
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
fmt.Printf("GC Pauses: %v\n", stats.PauseNs)
fmt.Printf("GC CPU: %.2f%%\n", stats.GCCPUFraction*100)
Quando usare Green Tea GC:
- ✅ Apps con molti small objects (<1KB)
- ✅ High allocation rate (>1GB/sec)
- ✅ GC-sensitive workloads (sub-millisecond latency)
- ⚠️ Experimental - test before production!
Container-Aware GOMAXPROCS
GOMAXPROCS ora dinamico e container-aware su Linux!
❌ Prima - GOMAXPROCS statico:
// Container con limit 2 CPU
// GOMAXPROCS = 8 (num CPU host)
// ❌ Oversubscription! Performance poor
runtime.GOMAXPROCS(0) // Returns 8 (wrong!)
✅ Go 1.25 - Container-aware:
// Container con CPU limit 2.5
// GOMAXPROCS = 2 (floor of 2.5)
// ✅ Ottimale!
runtime.GOMAXPROCS(0) // Returns 2 (correct!)
Come funziona:
# Kubernetes CPU limit
apiVersion: v1
kind: Pod
spec:
containers:
- name: myapp
image: myapp:latest
resources:
limits:
cpu: "2" # Go 1.25 set GOMAXPROCS=2
requests:
cpu: "1" # Ignores requests (solo limits)
Aggiornamento dinamico:
// GOMAXPROCS si aggiorna automaticamente!
// Container scale da 2 CPU → 4 CPU
// GOMAXPROCS: 2 → 4 (automatico!)
// Monitoring
go func() {
ticker := time.NewTicker(10 * time.Second)
for range ticker.C {
fmt.Printf("Current GOMAXPROCS: %d\n", runtime.GOMAXPROCS(0))
}
}()
Override manuale (se necessario):
// Disable auto-adjustment
runtime.GOMAXPROCS(4) // Fixed a 4
// O env variable
export GOMAXPROCS=4
Vantaggi:
- ✅ No oversubscription in containers
- ✅ Dynamic scaling se CPU limit cambia
- ✅ Zero config: Funziona automaticamente
- ✅ Better resource usage: CPU non sprecate
testing/synctest Package (Stable!)
Package per testing concorrenza ora stabile!
❌ Prima - Test concurrency difficile:
func TestConcurrent(t *testing.T) {
done := make(chan bool)
go func() {
time.Sleep(100 * time.Millisecond)
done <- true
}()
select {
case <-done:
// OK
case <-time.After(1 * time.Second):
t.Fatal("timeout") // ❌ Flaky test!
}
}
✅ Go 1.25 - synctest.Test:
import "testing/synctest"
func TestConcurrent(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
done := make(chan bool)
go func() {
// ✨ Time virtualizzato!
time.Sleep(100 * time.Millisecond)
done <- true
}()
<-done // ✅ No timeout! Test istantaneo
})
}
Come funziona synctest:
// Virtual time in "bubble"
synctest.Test(t, func(t *testing.T) {
start := time.Now()
// Goroutine che aspetta
go func() {
time.Sleep(1 * time.Hour) // ✨ Istantaneo!
fmt.Println("Done!")
}()
synctest.Wait() // Aspetta goroutines bloccate
elapsed := time.Since(start)
fmt.Printf("Elapsed: %v\n", elapsed) // ~0ms!
})
Real-world example - Rate limiter test:
type RateLimiter struct {
rate time.Duration
lastTick time.Time
}
func (r *RateLimiter) Allow() bool {
now := time.Now()
if now.Sub(r.lastTick) < r.rate {
return false
}
r.lastTick = now
return true
}
func TestRateLimiter(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
limiter := &RateLimiter{rate: 1 * time.Second}
// First call
if !limiter.Allow() {
t.Fatal("should allow")
}
// Immediate second call
if limiter.Allow() {
t.Fatal("should block")
}
// ✨ Virtual time advance
time.Sleep(1 * time.Second)
// Now should allow
if !limiter.Allow() {
t.Fatal("should allow after 1s")
}
// Test completa in <1ms invece di 2+ secondi!
})
}
Vantaggi:
- ✅ Fast tests: No real sleep/timeout
- ✅ Deterministic: No flaky tests
- ✅ Easy: Drop-in per test concurrency
- ✅ Virtual time: time.Sleep istantaneo
Core Types Removal
Go spec semplificata rimuovendo concetto Core Types!
Context:
Go 1.18 introdusse "core types" per gestire generics, complicando la spec.
❌ Prima - Core types ovunque:
// Spec pre-1.25
// "For a channel ch, close(ch) is valid if the core type of ch is a channel..."
// ❌ Devi capire "core types" anche per operazioni base!
✅ Go 1.25 - Spec semplice:
// Spec 1.25
// "For a channel ch, close(ch) records that no more values will be sent"
// ✅ Comprensibile senza sapere niente di generics!
// Solo se usi type parameters:
// "If ch is a type parameter, all types in its type set must be channels..."
Impact per sviluppatori:
// Il codice funziona esattamente come prima!
func Send[T any, C ~chan T](ch C, val T) {
ch <- val
close(ch) // ✅ Stesso behavior, spec più chiara
}
Vantaggi:
- ✅ Spec più semplice: Meno concetti da imparare
- ✅ Non-generic code: Indipendente da generics
- ✅ Future flexibility: Apre porta a miglioramenti
Flight Recorder API
Nuovo trace recorder in-memory!
import (
"os"
"runtime/trace"
)
func main() {
// ✅ Crea flight recorder
rec, err := trace.NewFlightRecorder(trace.FlightRecorderConfig{
Size: 10 * 1024 * 1024, // 10MB buffer
})
if err != nil {
panic(err)
}
defer rec.Close()
// Run app logic...
processRequests()
// Su errore/evento, snapshot trace
if errorDetected {
f, _ := os.Create("crash-trace.out")
rec.WriteTo(f, "")
f.Close()
}
}
Vantaggi:
- ✅ Low overhead: Solo recent events in memory
- ✅ On-demand: Snapshot solo quando serve
- ✅ Small traces: Non GB di trace data
- ✅ Production-safe: Sempre attivo senza impatto
🚀 Compiler & Toolchain
DWARF 5 Debug Info
# Go 1.25 usa DWARF 5 di default
go build main.go
# Risultato:
# - Binary debug info: -30% size
# - Link time: -20% faster
# - GDB/Delve: Supporto completo
Disable se necessario:
GOEXPERIMENT=nodwarf5 go build
Stack Allocation Optimizer
Compiler alloca più slices su stack:
// Ora su stack invece che heap!
func process() []int {
data := make([]int, 100) // ✅ Stack alloc (se escape analysis OK)
for i := range data {
data[i] = i * 2
}
return data
}
Impact:
- ✅ -15-25% allocations in hot paths
- ✅ Better GC pressure
- ⚠️ Può amplificare bugs con unsafe.Pointer
Debug problemi:
# Trova allocation problematica
go build -gcflags=-d=variablemake=debug
# Disable tutte le nuove stack allocs
go build -gcflags=all=-d=variablemakehash=n
Nil Pointer Check Fix
Compiler bug FIXATO - nil checks ora corretti!
❌ Bug Go 1.21-1.24:
f, err := os.Open("nonExistent")
name := f.Name() // ❌ Non panic! (bug)
if err != nil {
return
}
println(name)
✅ Go 1.25 - Corretto:
f, err := os.Open("nonExistent")
name := f.Name() // ✅ PANIC qui! (corretto)
if err != nil {
return
}
println(name)
Fix per codice broken:
// ✅ Check err PRIMA di usare f
f, err := os.Open("file")
if err != nil {
return err
}
name := f.Name() // Safe
📦 Standard Library
go vet Analyzers
Nuovi analyzers:
# waitgroup analyzer
go vet ./...
# Detect: wg.Add() after wg.Wait()
# hostport analyzer
go vet ./...
# Detect: Invalid host:port parsing
Esempio waitgroup:
// ❌ go vet detect bug
var wg sync.WaitGroup
wg.Wait()
wg.Add(1) // ERROR: Add after Wait!
Esempio hostport:
// ❌ go vet detect bug
host, port, _ := net.SplitHostPort("[::1:8080") // Malformed!
archive/tar Symlink Support
import "archive/tar"
import "io/fs"
// ✅ Writer.AddFS ora supporta symlink!
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
fsys := os.DirFS(".")
tw.AddFS(fsys) // Symlink preservati!
encoding/asn1 Stricter Parsing
// Parsing T61String/BMPString più strict
// Malformed encodings → error (prima accepted)
📊 Performance Benchmarks
| Metrica | Go 1.24 | Go 1.25 | Improvement |
|---|---|---|---|
| JSON Unmarshal | 2400ns | 280ns | 8.5x |
| JSON Marshal | 1200ns | 120ns | 10x |
| GC Overhead (GreenTea) | 40% | 25% | -37.5% |
| Stack Allocs | 100% | 75% | -25% |
| Binary Debug Size | 100% | 70% | -30% |
🔄 Migration Guide
Upgrade Go
# Download Go 1.25
wget https://go.dev/dl/go1.25.linux-amd64.tar.gz
# Install
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.25.linux-amd64.tar.gz
# Verify
go version
# go version go1.25 linux/amd64
Test JSON v2
# Try JSON v2
GOEXPERIMENT=jsonv2 go test ./...
# Benchmark
GOEXPERIMENT=jsonv2 go test -bench=. ./...
Test Green Tea GC
# Try new GC
GOEXPERIMENT=greenteagc go run main.go
# Monitor impact
GODEBUG=gctrace=1 GOEXPERIMENT=greenteagc go run main.go
Fix Nil Pointer Bugs
# Audit code per bug pattern
git grep -n "err :=" | grep "\\..*() "
# Fix: check err BEFORE uso result
💡 Conclusioni
Go 1.25 è una release performance-focused:
✅ JSON v2 - 10x faster per API/microservices ✅ Green Tea GC - -37% overhead per GC-heavy apps ✅ Container-aware GOMAXPROCS - Ottimale in K8s ✅ testing/synctest - Fast & deterministic concurrent tests ✅ Core Types removal - Spec più semplice ✅ Flight Recorder - Production-safe tracing ✅ Compiler fixes - Nil check bug finalmente fixato
Raccomandazione:
- ✅ Production apps: Upgrade e test JSON v2
- ⚠️ GreenTea GC: Test in staging prima
- ✅ K8s/containers: Immediate benefits da GOMAXPROCS
- ✅ Concurrent code: Usa synctest per test