Go

How to Generate UUID in Go

Using github.com/google/uuid

Generate UUIDs in Go using the official Google UUID package. Supports v1, v4, v5, v6, and v7 with excellent performance and comprehensive functionality for Go applications.

Generate UUID in Go

id := uuid.New()
550e8400-e29b-41d4-a716-446655440000

Installation

Install the Google UUID package:

Terminal
go get github.com/google/uuid

Quick Start - Generate UUID v4

The simplest way to generate a random UUID:

main.go
package main

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

func main() {
    // Generate UUID v4 (random)
    id := uuid.New()
    fmt.Println(id)  
    // Output: 550e8400-e29b-41d4-a716-446655440000
    
    // Or use uuid.NewString() for string directly
    idStr := uuid.NewString()
    fmt.Println(idStr)
    
    // Generate multiple UUIDs
    for i := 0; i < 5; i++ {
        fmt.Println(uuid.New())
    }
}

All UUID Versions

Generate different UUID versions:

Go
package main

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

func main() {
    // UUID v4 - Random (most common)
    v4 := uuid.New()
    fmt.Printf("v4: %s\n", v4)
    
    // Or explicit v4
    v4Random, err := uuid.NewRandom()
    if err != nil {
        panic(err)
    }
    fmt.Printf("v4 (explicit): %s\n", v4Random)

    // UUID v1 - Timestamp + MAC
    v1, err := uuid.NewUUID()
    if err != nil {
        panic(err)
    }
    fmt.Printf("v1: %s\n", v1)

    // UUID v7 - Unix timestamp (sortable) - requires v1.6+
    v7, err := uuid.NewV7()
    if err != nil {
        panic(err)
    }
    fmt.Printf("v7: %s\n", v7)

    // UUID v6 - Reordered timestamp
    v6, err := uuid.NewV6()
    if err != nil {
        panic(err)
    }
    fmt.Printf("v6: %s\n", v6)

    // UUID v5 - SHA-1 hash (deterministic)
    v5 := uuid.NewSHA1(uuid.NameSpaceDNS, []byte("example.com"))
    fmt.Printf("v5: %s\n", v5)

    // UUID v3 - MD5 hash (deterministic)
    v3 := uuid.NewMD5(uuid.NameSpaceDNS, []byte("example.com"))
    fmt.Printf("v3: %s\n", v3)
}

Parse & Validate UUID

Parse UUID strings and validate format:

Go
package main

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

func main() {
    // Parse from string
    id, err := uuid.Parse("550e8400-e29b-41d4-a716-446655440000")
    if err != nil {
        log.Fatal("Invalid UUID:", err)
    }
    fmt.Println("Parsed UUID:", id)
    
    // MustParse (panics if invalid)
    id2 := uuid.MustParse("550e8400-e29b-41d4-a716-446655440000")
    
    // Validate without parsing
    func isValidUUID(s string) bool {
        _, err := uuid.Parse(s)
        return err == nil
    }
    
    fmt.Println(isValidUUID("550e8400-e29b-41d4-a716-446655440000"))  // true
    fmt.Println(isValidUUID("not-a-uuid"))  // false
    
    // Get version
    fmt.Println("Version:", id.Version())  // 4
    
    // Get variant
    fmt.Println("Variant:", id.Variant())  // RFC4122
    
    // Nil UUID
    var nilUUID uuid.UUID  // Zero value is Nil
    fmt.Println(nilUUID == uuid.Nil)  // true
    
    // Check if nil
    if id == uuid.Nil {
        fmt.Println("UUID is nil")
    }
}

UUID with GORM (Database)

Use UUIDs with GORM ORM for PostgreSQL/MySQL:

Go - GORM
package main

import (
    "github.com/google/uuid"
    "gorm.io/gorm"
    "gorm.io/driver/postgres"
    "time"
)

type User struct {
    ID        uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()"`
    Name      string    `gorm:"not null"`
    Email     string    `gorm:"uniqueIndex;not null"`
    CreatedAt time.Time
    UpdatedAt time.Time
}

// Hook to generate UUID before create
func (u *User) BeforeCreate(tx *gorm.DB) error {
    if u.ID == uuid.Nil {
        u.ID = uuid.New()
    }
    return nil
}

func main() {
    dsn := "host=localhost user=postgres password=secret dbname=mydb port=5432"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        panic(err)
    }

    // Auto-migrate
    db.AutoMigrate(&User{})

    // Create user
    user := User{
        Name:  "John Doe",
        Email: "john@example.com",
    }
    
    result := db.Create(&user)
    if result.Error != nil {
        panic(result.Error)
    }
    
    fmt.Printf("Created user with ID: %s\n", user.ID)

    // Query by UUID
    var foundUser User
    db.Where("id = ?", user.ID).First(&foundUser)
    fmt.Printf("Found: %s\n", foundUser.Name)
    
    // Query with string UUID
    uuidStr := "550e8400-e29b-41d4-a716-446655440000"
    parsedUUID, _ := uuid.Parse(uuidStr)
    db.Where("id = ?", parsedUUID).First(&foundUser)
}

UUID in HTTP API (Gin Framework)

Use UUIDs in REST API endpoints:

Go - Gin
package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
)

type CreateUserRequest struct {
    Name  string `json:"name" binding:"required"`
    Email string `json:"email" binding:"required,email"`
}

type UserResponse struct {
    ID    uuid.UUID `json:"id"`
    Name  string    `json:"name"`
    Email string    `json:"email"`
}

func main() {
    r := gin.Default()

    // GET user by UUID
    r.GET("/users/:id", func(c *gin.Context) {
        idStr := c.Param("id")
        
        // Parse UUID
        id, err := uuid.Parse(idStr)
        if err != nil {
            c.JSON(http.StatusBadRequest, gin.H{
                "error": "Invalid UUID format",
            })
            return
        }
        
        // Fetch user (mock)
        user := UserResponse{
            ID:    id,
            Name:  "John Doe",
            Email: "john@example.com",
        }
        
        c.JSON(http.StatusOK, user)
    })

    // POST create user
    r.POST("/users", func(c *gin.Context) {
        var req CreateUserRequest
        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{
                "error": err.Error(),
            })
            return
        }
        
        // Create user with new UUID
        user := UserResponse{
            ID:    uuid.New(),
            Name:  req.Name,
            Email: req.Email,
        }
        
        c.JSON(http.StatusCreated, user)
    })

    r.Run(":8080")
}

Extract Timestamp from UUID v7

Get the timestamp embedded in UUID v7:

Go
package main

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

func main() {
    // Generate UUID v7
    v7, _ := uuid.NewV7()
    fmt.Printf("UUID v7: %s\n", v7)

    // Get timestamp from v7 UUID
    timestamp, ok := v7.Time()
    if ok {
        fmt.Printf("Timestamp: %s\n", timestamp)
        fmt.Printf("Unix: %d\n", timestamp.Unix())
    }
    
    // Create multiple v7 UUIDs (sortable by time)
    var uuids []uuid.UUID
    for i := 0; i < 5; i++ {
        v7, _ := uuid.NewV7()
        uuids = append(uuids, v7)
        time.Sleep(10 * time.Millisecond)
    }
    
    // They're naturally sorted by creation time
    for _, id := range uuids {
        ts, _ := id.Time()
        fmt.Printf("%s - %s\n", id, ts)
    }
}

UUID to/from Bytes

Go
package main

import (
    "encoding/base64"
    "encoding/hex"
    "fmt"
    "github.com/google/uuid"
)

func main() {
    id := uuid.New()
    
    // UUID is already [16]byte internally
    bytes := id[:]
    fmt.Printf("Bytes: %v\n", bytes)
    fmt.Printf("Length: %d\n", len(bytes))  // 16
    
    // From bytes
    var byteArray [16]byte
    copy(byteArray[:], bytes)
    fromBytes, err := uuid.FromBytes(bytes)
    if err != nil {
        panic(err)
    }
    fmt.Printf("From bytes: %s\n", fromBytes)
    
    // To hex string
    hexStr := hex.EncodeToString(bytes)
    fmt.Printf("Hex: %s\n", hexStr)
    
    // To Base64 (compact representation)
    base64Str := base64.StdEncoding.EncodeToString(bytes)
    fmt.Printf("Base64: %s\n", base64Str)
    
    // String representations
    fmt.Printf("String: %s\n", id.String())
    fmt.Printf("URN: %s\n", id.URN())
}

Custom Types with UUID

Create type-safe UUID wrappers:

Go
package main

import (
    "database/sql/driver"
    "fmt"
    "github.com/google/uuid"
)

// Type-safe UserID
type UserID uuid.UUID

func NewUserID() UserID {
    return UserID(uuid.New())
}

func (u UserID) String() string {
    return uuid.UUID(u).String()
}

func (u UserID) MarshalJSON() ([]byte, error) {
    return []byte(`"` + u.String() + `"`), nil
}

func (u *UserID) UnmarshalJSON(data []byte) error {
    str := string(data[1 : len(data)-1])
    id, err := uuid.Parse(str)
    if err != nil {
        return err
    }
    *u = UserID(id)
    return nil
}

// GORM/SQL Scanner interface
func (u *UserID) Scan(value interface{}) error {
    var id uuid.UUID
    if err := id.Scan(value); err != nil {
        return err
    }
    *u = UserID(id)
    return nil
}

func (u UserID) Value() (driver.Value, error) {
    return uuid.UUID(u).Value()
}

// Usage
type User struct {
    ID    UserID
    Name  string
}

func main() {
    user := User{
        ID:   NewUserID(),
        Name: "Alice",
    }
    
    fmt.Printf("User ID: %s\n", user.ID)
}

Standard Library database/sql

Use UUIDs with standard database/sql:

Go - database/sql
package main

import (
    "database/sql"
    "fmt"
    "log"
    "github.com/google/uuid"
    _ "github.com/lib/pq"  // PostgreSQL driver
)

func main() {
    db, err := sql.Open("postgres", 
        "host=localhost user=postgres password=secret dbname=mydb")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // Insert with UUID
    id := uuid.New()
    _, err = db.Exec(
        "INSERT INTO users (id, name, email) VALUES ($1, $2, $3)",
        id, "Bob Wilson", "bob@example.com",
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Inserted user with ID: %s\n", id)

    // Query by UUID
    var name string
    var email string
    var queriedID uuid.UUID
    
    err = db.QueryRow(
        "SELECT id, name, email FROM users WHERE id = $1", 
        id,
    ).Scan(&queriedID, &name, &email)
    
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Found: %s (%s) - %s\n", name, email, queriedID)
}

Other Programming Language UUID Guides

Copied!