Install TypeID Go
mainTo add the TypeID Go library as a dependency to your Go module, use the go get command with the v2 module path.
go get go.jetify.com/typeid/v2repository·main·Indexed 42 days ago
https://github.com/jetify-com/typeid-goA Go implementation of TypeIDs, providing type-safe, globally unique identifiers based on the UUIDv7 standard. Designed for use as primary identifiers in databases, APIs, and distributed systems, the v2 library includes support for generating, parsing, and converting TypeIDs, as well as implementations for encoding.TextMarshaler, encoding.TextUnmarshaler, sql.Scanner, and driver.Valuer interfaces.
To add the TypeID Go library as a dependency to your Go module, use the go get command with the v2 module path.
go get go.jetify.com/typeid/v2When checking the state of a TypeID, it is important to distinguish between a zero-value ID and an ID that simply has a zero suffix.
HasSuffix(): Returns false if the suffix is the zero suffix (00000000000000000000000000). This check is independent of the prefix. For example, prefix_00000000000000000000000000 will return false.IsZero(): Returns true only if the TypeID has an empty prefix AND a zero suffix. An empty struct TypeID{} is considered a zero ID.The typeid package provides several methods for creating and interpreting TypeIDs.
MustGenerate(prefix string): Generates a new TypeID with the specified prefix. It will panic if the prefix is invalid.Generate(prefix string): Generates a new TypeID with the specified prefix and returns an error if the prefix is invalid.Parse(id string): Parses an existing TypeID string into a TypeID object.FromUUID(prefix string, uuid string): Converts a standard UUID string into a TypeID with the given prefix.import (
"fmt"
"log"
"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)
}Use MustGenerate(prefix string) when you want to create a new TypeID but do not want to handle errors manually. This function will panic if the provided prefix is invalid. Use Generate() instead if you need robust error handling.
tid := typeid.MustGenerate("order")The TypeID type implements the sql.Scanner and driver.Valuer interfaces, allowing it to be used transparently with Go's database/sql package.
Value() method converts a TypeID into its string representation, making it compatible with database columns that store strings.Scan(src any) method allows reading TypeID values from database columns. It currently supports string types.Important Constraints:
TypeID does not support NULL values directly. If your database column is nullable, you must use sql.Null[TypeID] instead of TypeID to avoid a cannot scan NULL into TypeID error.TypeID will result in a validation error.string types are currently supported for scanning.// For nullable TypeID columns, use sql.Null[TypeID].
// Example usage in a struct:
type User struct {
ID typeid.TypeID
Slug sql.Null[typeid.TypeID] // Use this if the column can be NULL
}The AppendText(dst []byte) method appends the string representation of a TypeID to an existing byte slice dst and returns the extended buffer. This is an efficient way to build strings or byte slices without extra allocations.
If the TypeID is empty (zero value), it appends the ZeroSuffix to the buffer.
// Append a TypeID to an existing buffer
buffer := []byte("id: ")
tid := typeid.MustParse("prefix.uuid")
newBuffer, err := tid.AppendText(buffer)
// newBuffer is now []byte("id: prefix.uuid")Use FromUUID(prefix, uidStr string) to encode an existing UUID (provided as a hex string) into a TypeID format.
prefix: The prefix to use (pass "" for no prefix).uidStr: The UUID string to encode.Returns an error if the prefix is invalid or if the uidStr is not in a valid UUID format.
tid, err := typeid.FromUUID("account", "550e8400-e29b-41d4-a716-446655440000")
if err != nil {
// handle error
}When performing operations that validate TypeID formats, the package may return ErrValidation. This is a sentinel error used to indicate that a TypeID is malformed or invalid.
To check if an error is a validation error, use errors.Is(err, ErrValidation). The error may wrap an underlying cause (such as a base32 decoding error) which can be accessed via errors.Unwrap(err).
import (
"errors"
"fmt"
"github.com/jetify-com/typeid-go"
)
func handleResult(err error) {
if errors.Is(err, typeid.ErrValidation) {
fmt.Println("The provided TypeID is invalid")
} else if err != nil {
fmt.Printf("An unexpected error occurred: %v\n", err)
}
}Use Generate(prefix string) to create a new TypeID consisting of a provided prefix and a random suffix. The suffix is generated using a UUID v7 and encoded into a 26-character base32 string.
To create a TypeID without a prefix, pass an empty string ("").
tid, err := typeid.Generate("user")
if err != nil {
// handle error
}
// tid will be in the format "user_..."The TypeID type implements the standard Go encoding.TextMarshaler and encoding.TextUnmarshaler interfaces. This allows TypeID to be seamlessly used with encoders like encoding/json or encoding/xml.
MarshalText(): Encodes the TypeID as its string representation.UnmarshalText(text []byte): Parses a TypeID from the provided byte slice using the same logic as Parse().// Example of marshaling/unmarshaling via standard interfaces
var tid typeid.TypeID
// UnmarshalText
err := tid.UnmarshalText([]byte("prefix.uuid"))
if err != nil {
// handle error
}
// MarshalText
bytes, err := tid.MarshalText()Use FromBytes(prefix string, uidBytes []byte) to create a TypeID from a raw 16-byte UUID slice. This method is optimized for zero allocations during the conversion process.
prefix: The prefix to use (pass "" for no prefix).uidBytes: A byte slice that must be exactly 16 bytes long.Returns an error if uidBytes is not exactly 16 bytes or if the prefix is invalid.
// Assuming bytes is a 16-byte slice
tid, err := typeid.FromBytes("session", bytes)
if err != nil {
// handle error
}Use Parse(s string) to convert a string of the form <prefix>_<suffix> into a TypeID object.
If the string does not contain an underscore (_), the entire string is treated as the suffix with an empty prefix. If an underscore is present but the prefix is empty (e.g., "_suffix"), Parse will return an error.
tid, err := typeid.Parse("user_abc123")
if err != nil {
// handle error
}