typeid

package module
v2.0.0-alpha.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2025 License: Apache-2.0 Imports: 6 Imported by: 24

README

TypeID Go

A golang implementation of TypeIDs

Go Reference

TypeIDs are a modern, type-safe, globally unique identifier based on the upcoming UUIDv7 standard. They provide a ton of nice properties that make them a great choice as the primary identifiers for your data in a database, APIs, and distributed systems. Read more about TypeIDs in their spec.

This particular implementation provides a go library for generating and parsing TypeIDs.

Installation

To add this library as a dependency in your go module, run:

go get go.jetify.com/typeid/v2

Usage

This library provides a go implementation of TypeID:

import (
  "go.jetify.com/typeid/v2"
)

func example() {
  // Generate a new TypeID with a prefix (panics on invalid prefix)
  tid := typeid.MustGenerate("user")
  fmt.Println(tid)
  
  // Generate a new TypeID without a prefix
  tid = typeid.MustGenerate("")
  fmt.Println(tid)
  
  // Generate with error handling
  tid, err := typeid.Generate("user")
  if err != nil {
    log.Fatal(err)
  }
  
  // Parse an existing TypeID
  tid, _ = typeid.Parse("user_00041061050r3gg28a1c60t3gf")
  fmt.Println(tid)
  
  // Convert from UUID
  tid, _ = typeid.FromUUID("user", "018e5f71-6f04-7c5c-8123-456789abcdef")
  fmt.Println(tid)
}

For the full documentation, see this package's godoc.

Documentation

Overview

This particular implementation provides a go library for generating and parsing TypeIDs

Example (NullableColumns)

Example_nullableColumns demonstrates using sql.Null[TypeID] for nullable database columns. This is the recommended approach for handling nullable TypeID columns in Go applications.

var managerID sql.Null[typeid.TypeID]

// Scan NULL value from database
err := managerID.Scan(nil)
if err != nil {
	panic(err)
}
fmt.Printf("Is valid: %v\n", managerID.Valid)

// Scan actual TypeID value
err = managerID.Scan("user_00041061050r3gg28a1c60t3gf")
if err != nil {
	panic(err)
}
fmt.Printf("Is valid: %v\n", managerID.Valid)
fmt.Printf("Manager: %s\n", managerID.V.String())
Output:
Is valid: false
Is valid: true
Manager: user_00041061050r3gg28a1c60t3gf

Index

Examples

Constants

View Source
const ZeroSuffix = "00000000000000000000000000"

Variables

View Source
var ErrValidation error = &validationError{}

ErrValidation is a sentinel error for validation failures. Use errors.Is(err, ErrValidation) to check if an error is a validation error.

Functions

This section is empty.

Types

type TypeID

type TypeID struct {
	// contains filtered or unexported fields
}

TypeID is a unique identifier with a given type as defined by the TypeID spec

func FromBytes

func FromBytes(prefix string, uidBytes []byte) (TypeID, error)

FromBytes creates a TypeID from a prefix and 16-byte UUID with zero allocations. The bytes must be exactly 16 bytes long (standard UUID byte length). If you want to create an id without a prefix, pass an empty string for the prefix.

func FromUUID

func FromUUID(prefix string, uidStr string) (TypeID, error)

FromUUID encodes the given UUID (in hex string form) as a TypeID with the given prefix. If you want to create an id without a prefix, pass an empty string for the prefix.

Example

ExampleFromUUID demonstrates migrating from UUIDs to TypeIDs

// Existing UUID from legacy system
existingUUID := "550e8400-e29b-41d4-a716-446655440000"

// Convert to TypeID with appropriate prefix
customerID, err := typeid.FromUUID("customer", existingUUID)
if err != nil {
	panic(err)
}

fmt.Printf("Migrated customer ID: %s\n", customerID.String())
Output:
Migrated customer ID: customer_2n1t201rmv87aae5j4csam8000

func Generate

func Generate(prefix string) (TypeID, error)

Generate returns a new TypeID with the given prefix and a random suffix. If you want to create an id without a prefix, pass an empty string.

Example

ExampleGenerate demonstrates creating a new TypeID for a user entity

userID, err := typeid.Generate("user")
if err != nil {
	panic(err)
}

// Use the generated ID for a new user
fmt.Printf("Created new user with ID: %s\n", userID)
// Output format: Created new user with ID: user_[26-char-suffix]

func MustGenerate

func MustGenerate(prefix string) TypeID

MustGenerate returns a new TypeID with the given prefix and a random suffix. It panics if the prefix is invalid. Use Generate() if you need error handling.

func Parse

func Parse(s string) (TypeID, error)

Parse parses a TypeID from a string of the form <prefix>_<suffix>

Example

ExampleParse demonstrates parsing a TypeID from a string, such as from a URL parameter

// Parse a TypeID received from a client request
orderIDStr := "order_00041061050r3gg28a1c60t3gf"
orderID, err := typeid.Parse(orderIDStr)
if err != nil {
	fmt.Printf("Invalid order ID: %v\n", err)
	return
}

fmt.Printf("Processing order: %s\n", orderID.String())
fmt.Printf("Order type: %s\n", orderID.Prefix())
Output:
Processing order: order_00041061050r3gg28a1c60t3gf
Order type: order

func (TypeID) AppendText

func (tid TypeID) AppendText(dst []byte) ([]byte, error)

AppendText appends the text representation of the TypeID to dst and returns the extended buffer.

func (TypeID) Bytes

func (tid TypeID) Bytes() []byte

Bytes decodes the TypeID's suffix as a UUID and returns it's bytes

func (TypeID) HasSuffix

func (tid TypeID) HasSuffix() bool

HasSuffix returns true if the TypeID has a non-zero suffix.

This method returns false only when the suffix is the zero suffix: "00000000000000000000000000"

Note that HasSuffix() checks only the suffix value, regardless of the prefix. All of these examples would return `HasSuffix() == false`: + "prefix_00000000000000000000000000" + "test_00000000000000000000000000" + "00000000000000000000000000"

func (TypeID) IsZero

func (tid TypeID) IsZero() bool

IsZero returns true if the TypeID is the zero value (empty prefix and zero suffix).

Unlike HasSuffix(), IsZero() returns true only when both: + The prefix is empty (no type specified) + The suffix is the zero suffix "00000000000000000000000000"

Note that the empty struct TypeID{} is encoded as the zero id.

func (TypeID) MarshalText

func (tid TypeID) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface. It encodes a TypeID as a string using the same logic as String()

Example

ExampleTypeID_MarshalText demonstrates using TypeID in JSON APIs

// Define a struct for API responses
type Product struct {
	ID    typeid.TypeID `json:"id"`
	Name  string        `json:"name"`
	Price float64       `json:"price"`
}

// Create a product with TypeID
product := Product{
	ID:    typeid.MustParse("product_00041061050r3gg28a1c60t3gf"),
	Name:  "Widget",
	Price: 29.99,
}

// Marshal to JSON for API response
jsonData, err := json.Marshal(product)
if err != nil {
	panic(err)
}

fmt.Printf("%s\n", jsonData)
Output:
{"id":"product_00041061050r3gg28a1c60t3gf","name":"Widget","price":29.99}

func (TypeID) Prefix

func (tid TypeID) Prefix() string

Prefix returns the type prefix of the TypeID

func (*TypeID) Scan

func (tid *TypeID) Scan(src any) error

Scan implements the sql.Scanner interface so the TypeIDs can be read from databases transparently. Currently database types that map to string are supported.

Example

ExampleTypeID_Scan demonstrates reading TypeIDs from a database

// Simulate database row scan
var userID typeid.TypeID

// In real code, this would come from sql.Row.Scan()
dbValue := "user_00041061050r3gg28a1c60t3gf"
err := userID.Scan(dbValue)
if err != nil {
	panic(err)
}

fmt.Printf("Retrieved user %s from database\n", userID.String())
Output:
Retrieved user user_00041061050r3gg28a1c60t3gf from database

func (TypeID) String

func (tid TypeID) String() string

String returns the TypeID in it's canonical string representation of the form: <prefix>_<suffix> where <suffix> is the canonical base32 representation of the UUID

func (TypeID) Suffix

func (tid TypeID) Suffix() string

Suffix returns the suffix of the TypeID in it's canonical base32 representation.

func (TypeID) UUID

func (tid TypeID) UUID() string

UUID decodes the TypeID's suffix as a UUID and returns it as a hex string

func (*TypeID) UnmarshalText

func (tid *TypeID) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface. It parses a TypeID from a string using the same logic as FromString()

Example

ExampleTypeID_UnmarshalText demonstrates parsing TypeID from JSON requests

// JSON payload from client request
jsonPayload := `{
		"user_id": "user_00041061050r3gg28a1c60t3gf",
		"product_id": "product_00041061050r3gg28a1c60t3gg",
		"quantity": 2
	}`

// Define request struct
type OrderRequest struct {
	UserID    typeid.TypeID `json:"user_id"`
	ProductID typeid.TypeID `json:"product_id"`
	Quantity  int           `json:"quantity"`
}

// Parse the request
var req OrderRequest
err := json.Unmarshal([]byte(jsonPayload), &req)
if err != nil {
	panic(err)
}

fmt.Printf("Order from user %s for product %s\n", req.UserID.Prefix(), req.ProductID.Prefix())
Output:
Order from user user for product product

func (TypeID) Value

func (tid TypeID) Value() (driver.Value, error)

Value implements the sql.Valuer interface so that TypeIDs can be written to databases transparently. Currently, TypeIDs map to strings.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL