Scanning database...
Tools
Articles

No matches found for ""

View All Results
Developer Lab

UUID in Go

Production-ready implementation guide with CSPRNG-backed code snippets.



Generate UUID in Go

github.com/google/uuid is the Go standard — maintained by Google, backed by crypto/rand (OS CSPRNG). uuid.New() for v4, uuid.NewString() for a string directly, uuid.NewV7() for time-ordered.

Quick Reference

Function Version Sortable Use Case
uuid.New() v4 No General purpose — returns uuid.UUID type
uuid.NewString() v4 No Returns string directly — convenience wrapper
uuid.NewV7() v7 Yes Time-ordered — database PKs, event logs
uuid.Parse() any Parse and validate — returns error on invalid input

Primary Implementation

Production Ready
go snippet
package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    // UUID v4 — random, crypto/rand-backed, zero unsafe
    id := uuid.New()
    fmt.Println(id)
    // → f47ac10b-58cc-4372-a567-0e02b2c3d479

    // As a string directly (convenience)
    idStr := uuid.NewString()

    // uuid.UUID is [16]byte — value type, no heap allocation
    var raw [16]byte = id

    // Parse and validate an existing UUID string
    parsed, err := uuid.Parse("f47ac10b-58cc-4372-a567-0e02b2c3d479")
    if err != nil {
        fmt.Printf("Invalid UUID: %v\n", err)
        return
    }
    fmt.Printf("Version: %d\n", parsed.Version()) // → 4

    // Generate multiple
    ids := make([]uuid.UUID, 5)
    for i := range ids {
        ids[i] = uuid.New()
    }
}

All UUID Versions

UUID v4 — Random (recommended default)

go snippet
import "github.com/google/uuid"

// Returns uuid.UUID ([16]byte) — value type, no heap allocation
id := uuid.New()
fmt.Println(id.String()) // → "550e8400-e29b-41d4-a716-446655440000"

// Or get a string directly
idStr := uuid.NewString()

UUID v7 — Time-ordered (database PKs)

go snippet
import "github.com/google/uuid"

// Millisecond-precision timestamp prefix — sorts chronologically
id, err := uuid.NewV7()
if err != nil {
    log.Fatal(err)
}
fmt.Println(id.String()) // → "018e8f6a-1b2c-7d3e-9f4a-5b6c7d8e9f0a"

UUID v5 — Deterministic / Namespace-based

go snippet
import "github.com/google/uuid"

// SHA-1 hash of namespace + name — same inputs always produce the same UUID
id := uuid.NewSHA1(uuid.NameSpaceDNS, []byte("example.com"))
fmt.Println(id.String()) // → always "cfbff0d1-9375-5685-968c-48ce8b15ae17"

Real-World Use Cases

1. gRPC interceptor — request tracing ID

go snippet
import (
    "context"
    "github.com/google/uuid"
    "google.golang.org/grpc"
)

func UnaryRequestIDInterceptor(
    ctx context.Context,
    req interface{},
    info *grpc.UnaryServerInfo,
    handler grpc.UnaryHandler,
) (interface{}, error) {
    requestID := uuid.NewString()
    ctx = context.WithValue(ctx, "requestID", requestID)
    return handler(ctx, req)
}

2. GORM model with UUID primary key

go snippet
import (
    "github.com/google/uuid"
    "gorm.io/gorm"
)

type Order struct {
    ID        uuid.UUID `gorm:"type:uuid;primaryKey"`
    CreatedAt time.Time
    Name      string
}

// Auto-assign UUID before create
func (o *Order) BeforeCreate(tx *gorm.DB) error {
    o.ID = uuid.New()
    return nil
}

3. Distributed tracing — correlation ID

go snippet
import (
    "net/http"
    "github.com/google/uuid"
)

func RequestIDMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        requestID := uuid.NewString()
        w.Header().Set("X-Request-ID", requestID)
        ctx := context.WithValue(r.Context(), "requestID", requestID)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

Common Mistakes

Using fmt.Sprintf to build UUID strings

Manually constructing UUID strings with fmt.Sprintf("%x-%x-4%x-...", ...) is error-prone and almost always produces non-compliant UUIDs. Use uuid.New() or uuid.NewString().

Not handling errors from uuid.Parse()

uuid.Parse() returns an error for invalid input. Always check the error — ignoring it means you may silently use a zero-value UUID (00000000-0000-0000-0000-000000000000).

Storing uuid.UUID as a string in structs

uuid.UUID is a [16]byte value type — no heap allocation. Storing it as a string in structs wastes memory and loses type safety. Convert to string only at the boundary.

How It Works

The google/uuid package uses Go's crypto/rand package for entropy, which calls the OS CSPRNG — /dev/urandom on Linux/macOS and CryptGenRandom on Windows.

uuid.UUID is defined as type UUID [16]byte — a value type. Passing it around copies 16 bytes on the stack with zero heap allocation.

Output Formats

id.String()

f47ac10b-58cc-4372-a567-0e02b2c3d479

uuid.NewString()

f47ac10b-58cc-4372-a567-0e02b2c3d479

id[:] — []byte (16 bytes)

[0xf4 0x7a 0xc1 0x0b ...]

Best Practices

Store uuid.UUID in structs — only call .String() at API/DB boundaries.

Always handle the error from uuid.Parse() — never ignore it.

Use uuid.NewV7() for database PKs — sequential inserts avoid B-tree fragmentation.

Performance

Go generates roughly 5–10 million UUIDs/second. The uuid.UUID type is [16]byte — zero heap allocations when stored in structs.

The .String() call allocates a string. For high-throughput scenarios, use uuid.NewString() which combines generation and formatting in one call.

Installation

go get github.com/google/uuid

Requires Go 1.16+. The package is maintained by Google and has no transitive dependencies.

Security

Entropy source: crypto/rand → OS CSPRNG (/dev/urandom on Linux/macOS, CryptGenRandom on Windows). Cryptographically secure.

Suitable for session tokens, CSRF tokens, and API keys. Never use math/rand for UUID generation.