Documentation
¶
Overview ¶
Pacote loghubuuid implementa a geração de identificadores UUIDv7 (RFC 9562) com três níveis de precisão temporal.
O UUIDv7 é um identificador de 128 bits ordenável no tempo: os bits mais significativos carregam o instante de criação, de modo que a ordenação lexicográfica das strings coincide com a ordem cronológica.
Esta biblioteca estende o padrão guardando precisão sub-milissegundo dentro dos campos "aleatórios" do UUID, em três níveis:
Level1: apenas milissegundos (48 bits padrão). rand_a e rand_b
totalmente aleatórios. Compatível 100% com UUIDv7 comum.
Level2: invade rand_a (12 bits) para guardar os microssegundos
(0-999) do instante. rand_b continua aleatório.
Level3: invade rand_a para os microssegundos e ocupa os 10 bits
mais altos de rand_b para os nanossegundos (0-999). Os
52 bits restantes de rand_b continuam aleatórios.
Em todos os níveis a versão (7) e a variante (RFC) são preservadas, portanto o resultado é sempre um UUID válido.
Concorrência: o tipo Generator é seguro para uso simultâneo por centenas de goroutines. Crie um único Generator no boot da aplicação (ou use as funções de pacote, que usam um gerador padrão interno).
Index ¶
- Variables
- func BinaryToString(u UUID) string
- func ClockSequence() int
- func GenerateString(level Level) string
- func IsInvalidLengthError(err error) bool
- func NewString() string
- func NodeID() []byte
- func SetClockSequence(seq int)
- func SetNodeID(id []byte) bool
- func Validate(s string) error
- func VariantString(v byte) string
- func VersionString(v byte) string
- type Domain
- type Generator
- type GregorianTime
- type Level
- type NullUUID
- func (n NullUUID) MarshalBinary() ([]byte, error)
- func (n NullUUID) MarshalJSON() ([]byte, error)
- func (n NullUUID) MarshalText() ([]byte, error)
- func (n *NullUUID) Scan(src any) error
- func (n *NullUUID) UnmarshalBinary(data []byte) error
- func (n *NullUUID) UnmarshalJSON(data []byte) error
- func (n *NullUUID) UnmarshalText(data []byte) error
- func (n NullUUID) Value() (driver.Value, error)
- type Time
- type UUID
- func FromBytes(b []byte) (UUID, error)
- func FromString(s string) (UUID, error)
- func Generate(level Level) UUID
- func GenerateHash(h hash.Hash, space UUID, name []byte, version byte) UUID
- func GenerateV1() UUID
- func GenerateV2(domain Domain, id uint32) UUID
- func GenerateV2Group() UUID
- func GenerateV2Person() UUID
- func GenerateV3(space UUID, name []byte) UUID
- func GenerateV4() UUID
- func GenerateV5(space UUID, name []byte) UUID
- func GenerateV6() UUID
- func GenerateV8(data [16]byte) UUID
- func GenerateV8Random() UUID
- func Must(u UUID, err error) UUID
- func MustParse(s string) UUID
- func New() UUID
- func NewDCEGroup() (UUID, error)
- func NewDCEPerson() (UUID, error)
- func NewDCESecurity(domain Domain, id uint32) (UUID, error)
- func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID
- func NewMD5(space UUID, data []byte) UUID
- func NewRandom() (u UUID, err error)
- func NewRandomFromReader(r io.Reader) (UUID, error)
- func NewSHA1(space UUID, data []byte) UUID
- func NewUUID() (UUID, error)
- func NewV6() (UUID, error)
- func NewV7() (u UUID, err error)
- func NewV7FromReader(r io.Reader) (UUID, error)
- func Parse(s string) (UUID, error)
- func ParseBytes(b []byte) (UUID, error)
- func StringToBinary(s string) (UUID, error)
- func (u UUID) AppendText(dst []byte) ([]byte, error)
- func (u UUID) AppendTo(dst []byte) []byte
- func (u UUID) Bytes() []byte
- func (u UUID) ClockSequence() (int, bool)
- func (u UUID) Compare(other UUID) int
- func (u UUID) Domain() (Domain, bool)
- func (u UUID) GregorianTime() (GregorianTime, bool)
- func (u UUID) ID() (uint32, bool)
- func (u UUID) IsMax() bool
- func (u UUID) IsValid() bool
- func (u UUID) IsZero() bool
- func (u UUID) MarshalBinary() ([]byte, error)
- func (u UUID) MarshalText() ([]byte, error)
- func (u UUID) NodeID() []byte
- func (u *UUID) Scan(src any) error
- func (u UUID) String() string
- func (u UUID) Timestamp() (time.Time, bool)
- func (u UUID) TimestampWithLevel(level Level) (time.Time, bool)
- func (u UUID) URN() string
- func (u *UUID) UnmarshalBinary(data []byte) error
- func (u *UUID) UnmarshalText(data []byte) error
- func (u UUID) Value() (driver.Value, error)
- func (u UUID) Variant() byte
- func (u UUID) Version() byte
- type UUIDs
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // NameSpaceDNS é o espaço de nomes de domínio. NameSpaceDNS = MustParse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") // NameSpaceURL é o espaço de nomes de URL. NameSpaceURL = MustParse("6ba7b811-9dad-11d1-80b4-00c04fd430c8") // NameSpaceOID é o espaço de nomes de OID da ISO. NameSpaceOID = MustParse("6ba7b812-9dad-11d1-80b4-00c04fd430c8") // NameSpaceX500 é o espaço de nomes de nome distinto X.500. NameSpaceX500 = MustParse("6ba7b814-9dad-11d1-80b4-00c04fd430c8") )
Espaços de nomes conhecidos, definidos no apêndice da RFC 9562.
var ( // ErrInvalidLength indica comprimento incompatível com todos os // formatos aceitos. ErrInvalidLength error = &formatError{"loghubuuid: comprimento invalido para string de UUID"} // ErrInvalidBrackets indica a forma entre chaves malformada. ErrInvalidBrackets error = &formatError{"loghubuuid: chaves invalidas em string de UUID"} )
Erros mais específicos devolvidos por Parse e ParseBytes. Todos embrulham ErrInvalidFormat, portanto errors.Is(err, ErrInvalidFormat) continua verdadeiro e quem já trata o sentinela antigo não precisa mudar nada.
FromString e StringToBinary não mudaram: continuam devolvendo exatamente ErrInvalidFormat, inclusive para comparação direta com o operador de igualdade.
var ErrEntropySource = errors.New("loghubuuid: falha ao ler da fonte de entropia")
ErrEntropySource indica que a fonte de entropia informada pelo chamador não conseguiu entregar os bytes pedidos.
var ErrInvalidFormat = errors.New("loghubuuid: string de UUID em formato inválido")
ErrInvalidFormat indica que a string fornecida não está no formato canônico de UUID (8-4-4-4-12 dígitos hexadecimais).
var ErrInvalidScanType = errors.New("loghubuuid: tipo nao suportado na leitura de UUID")
ErrInvalidScanType indica que o valor lido do banco não é conversível para UUID.
var Max = UUID{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}
Max é o UUID com todos os 128 bits em um, definido pela RFC 9562 como limite superior de faixa. Não altere o valor desta variável.
Functions ¶
func BinaryToString ¶
BinaryToString é um apelido explícito para o método String(): converte o binário de 128 bits na string canônica.
func ClockSequence ¶ added in v0.3.0
func ClockSequence() int
ClockSequence devolve a sequência de relógio de 14 bits em uso pelos geradores de versão 1, 2 e 6, inicializando-a se ainda não houver uma.
func GenerateString ¶
GenerateString produz um UUID em string usando o gerador padrão do pacote.
Example ¶
A forma mais curta: as funções de pacote usam um gerador padrão interno, já pronto e seguro para concorrência.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
s1 := uuid.GenerateString(uuid.Level1) // só milissegundos (UUIDv7 padrão)
s2 := uuid.GenerateString(uuid.Level2) // até microssegundos (rand_a)
s3 := uuid.GenerateString(uuid.Level3) // até nanossegundos (rand_a + rand_b)
fmt.Println(len(s1), len(s2), len(s3))
}
Output: 36 36 36
func IsInvalidLengthError ¶ added in v0.3.0
IsInvalidLengthError informa se o erro veio de um comprimento incorreto, mesmo que tenha sido embrulhado por outra camada com fmt.Errorf e %w. Equivale a errors.Is(err, ErrInvalidLength), como no pacote github.com/google/uuid.
func NewString ¶ added in v0.3.0
func NewString() string
NewString produz um UUID de versão 4 com entropia criptográfica, já em formato canônico de texto.
func NodeID ¶ added in v0.3.0
func NodeID() []byte
NodeID devolve uma cópia dos 6 bytes de identificador de nó usados pelos UUIDs de versão 1, 2 e 6.
Por padrão o nó é sorteado uma única vez e marcado como aleatório. Esta biblioteca não lê interfaces de rede, para não arrastar o pacote net para dentro de quem só gera UUIDv7. Para usar um endereço MAC real, leia-o com net.Interfaces e entregue-o a SetNodeID.
func SetClockSequence ¶ added in v0.3.0
func SetClockSequence(seq int)
SetClockSequence fixa a sequência de relógio. Só os 14 bits baixos são usados. O valor -1 sorteia uma sequência ainda não usada neste processo.
A biblioteca mantém um piso de relógio por sequência: ao entrar em uma sequência, o próximo instante emitido é estritamente maior que qualquer instante já emitido com ela. Consequências:
- Um valor explícito pode ser reutilizado à vontade; voltar a uma sequência antiga herda o piso dela e nunca repete um UUIDv1/v6.
- O adiantamento acumulado do relógio interno só é descartado ao entrar em uma sequência inédita. Para ressincronizar com o relógio do sistema (por exemplo, após detectar que ele foi atrasado), use -1, que garante uma sequência inédita enquanto houver alguma livre.
Isto difere do pacote github.com/google/uuid, que descarta o piso em qualquer troca de sequência e por isso pode repetir um UUIDv1 ao voltar a uma sequência já usada.
func SetNodeID ¶ added in v0.3.0
SetNodeID fixa o identificador de nó a partir dos 6 primeiros bytes de id. Devolve falso, sem alterar nada, se id tiver menos de 6 bytes.
A chamada não mexe no piso do relógio interno: os instantes já emitidos continuam reservados, portanto reaplicar o mesmo nó nunca repete um UUIDv1 ou UUIDv6. Para descartar o adiantamento acumulado do relógio, sorteie uma sequência nova com SetClockSequence(-1).
Os bytes são copiados como estão. Se o valor não for um endereço MAC real, a RFC 9562 seção 6.10 pede o bit 0 do primeiro byte (multicast) ligado, para sinalizar que o nó não identifica uma placa de rede; essa marcação fica a cargo do chamador.
func Validate ¶ added in v0.3.0
Validate informa se a string é um UUID em algum dos formatos aceitos por Parse, devolvendo apenas o erro.
func VariantString ¶ added in v0.3.0
VariantString descreve em texto o código de variante devolvido por Variant.
Variant expõe apenas os 2 bits altos do byte 8, portanto o código 3 cobre tanto a variante reservada à Microsoft quanto a reservada para uso futuro; distinguir as duas exigiria um terceiro bit.
func VersionString ¶ added in v0.3.0
VersionString descreve em texto o número de versão devolvido por Version.
Types ¶
type Domain ¶ added in v0.3.0
type Domain byte
Domain é o domínio de identificação de um UUID de versão 2 (DCE Security), gravado no byte 9.
type Generator ¶
type Generator struct {
// contains filtered or unexported fields
}
Generator é o objeto que produz UUIDs. Deve ser criado uma única vez, no boot da aplicação, e pode ser compartilhado por muitas goroutines.
O gerador padrão tira entropia do gerador do runtime do Go (ChaCha8, uma instância por thread, semeada pelo sistema operacional), que não tem trava compartilhada e permite gerar milhões de IDs por segundo.
O valor zero de Generator NÃO é utilizável: use NewGenerator ou NewGeneratorWith. Por segurança, um Generator sem fonte de entropia (valor zero, ou ponteiro nulo) recorre ao gerador padrão do pacote em vez de entrar em pânico.
func NewCryptoGenerator ¶ added in v0.3.0
func NewCryptoGenerator() *Generator
NewCryptoGenerator cria um Generator cuja entropia vem inteiramente de crypto/rand, tornando os bits aleatórios imprevisíveis.
É mais lento que NewGenerator, que lê do gerador do runtime. Use este quando o identificador precisar resistir a quem tenta adivinhar o próximo valor. Lembre-se de que, mesmo assim, todo UUIDv7 revela o instante de criação por construção.
Example ¶
NewCryptoGenerator monta um gerador cuja entropia vem inteiramente de crypto/rand, para identificadores que precisem ser inadivinháveis. O gerador padrão é mais rápido, mas a recomendação para segredos continua sendo crypto/rand.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
gen := uuid.NewCryptoGenerator()
u := gen.Generate(uuid.Level1)
fmt.Println(u.Version(), u.Variant())
}
Output: 7 2
func NewGenerator ¶
func NewGenerator() *Generator
NewGenerator cria um Generator rápido e seguro para concorrência.
A entropia em tempo de execução vem das funções de pacote de math/rand/v2, que desde o Go 1.22 leem do gerador do runtime: uma instância de ChaCha8 por thread, semeada pelo sistema operacional na carga do programa. Não há trava compartilhada nem estado a manter, e a leitura é mais barata que a de um pool.
ATENÇÃO — o ChaCha8 é uma cifra de fluxo e resiste a predição, mas a própria documentação do Go recomenda crypto/rand para uso sensível a segurança. Além disso, todo UUIDv7 expõe o instante de criação por construção, independentemente da fonte de entropia. Não use estes identificadores como segredo (token de sessão, link privado, chave de recuperação); para esse fim, use NewCryptoGenerator ou monte o gerador com NewGeneratorWith.
func NewGeneratorWith ¶
NewGeneratorWith cria um Generator usando uma fonte de aleatoriedade personalizada. A função "source" deve devolver 64 bits aleatórios e PRECISA ser segura para uso concorrente (ela será chamada por várias goroutines ao mesmo tempo).
Use isto, por exemplo, para forçar entropia criptográfica (crypto/rand) em todas as gerações, abrindo mão de parte da velocidade em troca de imprevisibilidade total.
A fonte é chamada uma única vez por UUID nos níveis 2 e 3 (onde rand_a carrega o tempo) e duas vezes no nível 1.
Entra em pânico se source for nula: é um erro de configuração, que deve aparecer no boot e não na primeira geração.
func NewGeneratorWithReader ¶ added in v0.3.0
NewGeneratorWithReader cria um Generator que retira entropia de um io.Reader, formato usual das fontes da biblioteca padrão.
O leitor PRECISA ser seguro para uso concorrente, porque será chamado por várias goroutines ao mesmo tempo. crypto/rand.Reader satisfaz esse requisito.
Entra em pânico se reader for nulo, e também se uma leitura falhar durante a geração: uma fonte de entropia quebrada não pode degradar em silêncio para um gerador previsível.
Para a fonte criptográfica padrão, prefira NewCryptoGenerator.
func (*Generator) Generate ¶
Generate produz um UUID binário (128 bits) do nível informado, usando o instante atual (time.Now). Níveis desconhecidos são tratados como Level1 (totalmente padrão).
Layout dos 16 bytes (big-endian):
bytes 0..5 : unix_ts_ms .......... 48 bits (milissegundos desde epoch) byte 6 : 0x7_ | rand_a[11:8] . versão(4) + 4 bits altos de rand_a byte 7 : rand_a[7:0] ......... 8 bits baixos de rand_a (total 12 bits) byte 8 : 10_ | rand_b[61:56] . variante(2) + 6 bits altos de rand_b bytes 9..15: rand_b[55:0] ........ 56 bits restantes de rand_b (total 62 bits)
Onde, conforme o nível:
rand_a (12 bits) = microssegundos (0-999) nos níveis 2 e 3; aleatório no nível 1. rand_b[61:52] = nanossegundos (0-999) no nível 3; aleatório nos níveis 1 e 2. demais bits = aleatórios.
O campo de 48 bits de milissegundos comporta datas até 10889-08-02. Relógios anteriores à época Unix (1970-01-01) degradam para a própria época, em vez de produzirem um timestamp corrompido.
Example ¶
Em serviços de alto volume, crie um único Generator no boot e reutilize-o em todas as goroutines.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
gen := uuid.NewGenerator()
u := gen.Generate(uuid.Level3) // u é um uuid.UUID ([16]byte)
fmt.Println(u.Version(), u.Variant())
}
Output: 7 2
func (*Generator) GenerateString ¶
GenerateString produz um UUID do nível informado já no formato string canônico (8-4-4-4-12, minúsculas).
func (*Generator) GenerateV4 ¶ added in v0.3.0
GenerateV4 produz um UUID de versão 4: 122 bits aleatórios, sem qualquer informação de tempo, com versão e variante fixas.
A entropia vem da fonte deste Generator. No gerador padrão isso significa o ChaCha8 do runtime do Go, que resiste a predição mas cuja documentação recomenda crypto/rand para uso sensível a segurança: para identificadores que precisem ser segredo, monte o gerador com NewCryptoGenerator ou NewGeneratorWithReader.
O caminho é livre de alocações, como o dos demais geradores binários.
func (*Generator) GenerateV8 ¶ added in v0.3.0
GenerateV8 produz um UUID de versão 8 com os 122 bits livres preenchidos pela fonte de entropia deste Generator.
No gerador padrão a fonte é o ChaCha8 do runtime do Go; para segredos, prefira um gerador com entropia criptográfica. Veja o aviso em GenerateV4.
O resultado é indistinguível de um UUIDv4 quanto ao conteúdo; muda apenas o número de versão. Use quando precisar marcar identificadores como pertencentes a um esquema próprio.
type GregorianTime ¶ added in v0.3.0
type GregorianTime int64
GregorianTime conta intervalos de 100 nanossegundos desde 15/10/1582. É o formato do campo de tempo dos UUIDs de versão 1, 2 e 6.
func GetTime ¶ added in v0.3.0
func GetTime() (GregorianTime, uint16)
GetTime devolve o instante gregoriano corrente e a sequência de relógio em uso, avançando o relógio interno como faria uma geração de UUIDv1.
O segundo retorno traz os 14 bits da sequência com os dois bits de variante da RFC já posicionados (bit 15 ligado, bit 14 desligado), pronto para ser gravado nos bytes 8 e 9 de um UUIDv1 ou UUIDv6 — o mesmo formato devolvido pelo pacote github.com/google/uuid. Para obter apenas a sequência, mascare com 0x3FFF ou use ClockSequence.
func (GregorianTime) Time ¶ added in v0.3.0
func (t GregorianTime) Time() time.Time
Time devolve o instante como time.Time em UTC.
func (GregorianTime) UnixTime ¶ added in v0.3.0
func (t GregorianTime) UnixTime() (sec, nsec int64)
UnixTime converte o instante gregoriano para a época Unix, devolvendo segundos e a fração em nanossegundos.
type Level ¶
type Level uint8
Level define quanta precisão temporal é embutida no UUIDv7.
const ( // Level1 grava apenas milissegundos (48 bits). rand_a e rand_b // são totalmente aleatórios. É o UUIDv7 padrão da RFC 9562. Level1 Level = 1 // Level2 grava milissegundos + microssegundos (0-999) em rand_a. Level2 Level = 2 // Level3 grava milissegundos + microssegundos (em rand_a) + // nanossegundos (0-999) nos 10 bits mais altos de rand_b. Level3 Level = 3 )
type NullUUID ¶ added in v0.3.0
NullUUID representa um UUID que pode ser nulo no banco de dados, no mesmo espírito de sql.NullString.
Example ¶
NullUUID representa uma coluna que aceita NULL e viaja em JSON como a string canônica ou como null.
package main
import (
"encoding/json"
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
type Registro struct {
ID uuid.UUID `json:"id"`
Pai uuid.NullUUID `json:"pai"`
}
raiz := Registro{ID: uuid.MustParse("0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff")}
dados, _ := json.Marshal(raiz)
fmt.Println(string(dados))
var lido Registro
_ = json.Unmarshal([]byte(`{"id":"0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff","pai":"{0192F7C5-1A2B-7C3D-8E4F-AABBCCDDEEFF}"}`), &lido)
fmt.Println(lido.Pai.Valid, lido.Pai.UUID == lido.ID)
}
Output: {"id":"0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff","pai":null} true true
func (NullUUID) MarshalBinary ¶ added in v0.3.0
MarshalBinary grava os 16 bytes, ou nada quando não há valor.
func (NullUUID) MarshalJSON ¶ added in v0.3.0
MarshalJSON grava a string canônica, ou null quando não há valor.
func (NullUUID) MarshalText ¶ added in v0.3.0
MarshalText grava a string canônica, ou vazio quando não há valor.
func (*NullUUID) Scan ¶ added in v0.3.0
Scan implementa sql.Scanner. NULL, string vazia e fatia de bytes vazia produzem valor ausente (Valid falso), sem erro.
func (*NullUUID) UnmarshalBinary ¶ added in v0.3.0
UnmarshalBinary lê 16 bytes; entrada vazia produz valor ausente.
func (*NullUUID) UnmarshalJSON ¶ added in v0.3.0
UnmarshalJSON lê uma string JSON em qualquer formato aceito por Parse, ou null.
O caso comum, uma string sem sequências de escape, é lido direto dos bytes, sem alocar. Se a string contiver escapes JSON (por exemplo \u0030 no lugar de 0), a decodificação é delegada ao encoding/json, que os interpreta como faria para o tipo UUID; isso custa uma alocação e só acontece nesse caso raro. Erros de sintaxe JSON viram ErrInvalidFormat.
Em caso de erro o receptor não é alterado.
func (*NullUUID) UnmarshalText ¶ added in v0.3.0
UnmarshalText lê a string canônica; entrada vazia produz valor ausente.
type Time ¶
type Time struct {
// Seconds é o timestamp Unix em segundos desde 1970-01-01 UTC.
Seconds int64
// Milliseconds é a fração do segundo: sempre 0..999.
Milliseconds int
// Microseconds é lido de rand_a. Vale 0..999 (fração do
// milissegundo) quando o UUID é de Level2 ou Level3; em UUIDs de
// Level1 são 12 bits aleatórios, portanto 0..4095.
Microseconds int
// Nanoseconds é lido de rand_b[61:52]. Vale 0..999 (fração do
// microssegundo) quando o UUID é de Level3; em UUIDs de Level1 ou
// Level2 são 10 bits aleatórios, portanto 0..1023.
Nanoseconds int
}
Time reúne as propriedades temporais extraídas de um UUIDv7.
Os campos Microseconds e Nanoseconds só têm significado real se o UUID foi gerado com Level2/Level3 (micro) e Level3 (nano). Para UUIDs de Level1 esses campos contêm bits aleatórios — ainda assim, conforme a especificação, a importação os trata como tempo preciso e devolve o valor lido nos respectivos campos sem julgar a origem.
func Import ¶
Import recebe um UUIDv7 em string e devolve suas propriedades de tempo (segundos, milissegundos, microssegundos e nanossegundos). Retorna ErrInvalidFormat se a string não for um UUID canônico válido.
func ImportBinary ¶
ImportBinary extrai as propriedades de tempo de um UUID binário.
A leitura é "cega" quanto ao nível: ela sempre interpreta rand_a como microssegundos e os 10 bits altos de rand_b como nanossegundos, considerando dados aleatórios como se fossem o tempo preciso.
Example ¶
ImportBinary lê os campos de tempo de um UUIDv7. A leitura é cega quanto ao nível: rand_a é sempre interpretado como microssegundos e o topo de rand_b como nanossegundos, mesmo que o UUID seja de Nível 1 e esses bits sejam aleatórios.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
// UUIDv7 de Nível 3 montado à mão: 0x0192f7c51a2b ms desde a época,
// 0x1c3 = 451 microssegundos em rand_a e 0x393 = 915 nanossegundos
// nos 10 bits altos de rand_b.
u := uuid.MustParse("0192f7c5-1a2b-71c3-b930-0000aabbccdd")
t := uuid.ImportBinary(u)
fmt.Printf("seg=%d ms=%03d us=%03d ns=%03d\n",
t.Seconds, t.Milliseconds, t.Microseconds, t.Nanoseconds)
}
Output: seg=1730733742 ms=635 us=451 ns=915
type UUID ¶
type UUID [16]byte
UUID é o valor binário de 128 bits (16 bytes, big-endian / ordem de rede).
var Nil UUID
Nil é o UUID de valor zero, com os 128 bits em zero. Não altere o valor desta variável.
func FromBytes ¶ added in v0.3.0
FromBytes constrói um UUID a partir de exatamente 16 bytes em ordem de rede. Devolve ErrInvalidLength se o tamanho for outro.
func FromString ¶
FromString interpreta uma string canônica de UUID e devolve o valor binário de 128 bits. Aceita maiúsculas ou minúsculas. Retorna ErrInvalidFormat se o tamanho, os hifens ou os dígitos forem inválidos.
Em caso de erro o UUID devolvido é sempre o valor zero: nenhum byte parcialmente decodificado vaza para o chamador.
Example ¶
FromString aceita apenas a forma canônica 8-4-4-4-12, em maiúsculas ou minúsculas, e devolve ErrInvalidFormat para qualquer outra coisa.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
u, err := uuid.FromString("0192F7C5-1A2B-7C3D-8E4F-AABBCCDDEEFF")
if err != nil {
fmt.Println("erro:", err)
return
}
fmt.Println(u.String())
_, err = uuid.FromString("0192f7c51a2b7c3d8e4faabbccddeeff")
fmt.Println(err == uuid.ErrInvalidFormat) //nolint:errorlint // FromString devolve o sentinela puro; a comparação direta faz parte do contrato
}
Output: 0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff true
func GenerateHash ¶ added in v0.3.0
GenerateHash produz um UUID baseado em nome com a função de resumo informada, gravando o número de versão pedido.
Serve para reproduzir esquemas próprios de derivação. Para as versões da RFC use GenerateV3 ou GenerateV5. Apenas os 4 bits baixos de version são aproveitados, e a variante RFC é sempre aplicada.
func GenerateV1 ¶ added in v0.3.0
func GenerateV1() UUID
GenerateV1 produz um UUID de versão 1 (RFC 9562): tempo gregoriano de 60 bits, sequência de relógio de 14 bits e identificador de nó de 48 bits.
O tempo, a sequência e o nó vêm do estado compartilhado do pacote — veja SetNodeID e SetClockSequence. O relógio interno é estritamente crescente, portanto dois UUIDv1 gerados no mesmo processo nunca carregam o mesmo instante.
Layout dos 16 bytes (big-endian):
bytes 0..3 : time_low ................ 32 bits baixos do tempo bytes 4..5 : time_mid ................ 16 bits intermediários byte 6 : 0x1_ | time_hi[11:8] .... versão(4) + topo do tempo byte 7 : time_hi[7:0] ............ resto do topo (12 bits ao todo) byte 8 : 10_ | clock_seq[13:8] ... variante(2) + topo da sequência byte 9 : clock_seq[7:0] .......... resto da sequência bytes 10..15: node ................... 48 bits de identificador de nó
Atenção: o UUIDv1 não é ordenável lexicograficamente, porque os bits menos significativos do tempo vêm primeiro. Para ordenação cronológica use a versão 6 ou a versão 7.
Custo da ordem estrita: quando a geração é mais rápida que o tique de 100 nanossegundos, o relógio interno avança sozinho e o instante embutido fica à frente do relógio do sistema. Em rajadas longas esse adiantamento se acumula, na proporção de um tique por UUID. A RFC 9562 permite o comportamento, mas não conte com o carimbo de tempo de um UUIDv1 ou UUIDv6 como leitura fiel do relógio sob carga sustentada.
func GenerateV2 ¶ added in v0.3.0
GenerateV2 produz um UUID de versão 2 (DCE Security). Ele parte de um UUIDv1 e substitui dois campos: os 32 bits baixos do tempo passam a carregar o identificador local, e o byte baixo da sequência de relógio passa a carregar o domínio.
Consequência dessa troca: o UUIDv2 perde os 32 bits menos significativos do tempo, portanto o instante embutido tem resolução de poucos minutos e não deve ser lido como carimbo de tempo. Timestamp devolve falso para esta versão.
Atenção: o UUIDv2 identifica um principal — usuário, grupo ou organização — e não um evento. Os bits de tempo que sobram só mudam a cada 2^32 tiques de 100 nanossegundos, cerca de sete minutos, e o avanço de um tique por chamada do relógio interno cai justamente nos bits descartados. Portanto, chamadas repetidas com o mesmo domínio e o mesmo identificador, dentro da mesma janela, devolvem o MESMO UUID; duas chamadas consecutivas são iguais. Sem trocar a sequência de relógio, existem no máximo 64 valores distintos por janela.
A versão 2 é legado do DCE 1.1 e não é recomendada para sistemas novos.
func GenerateV2Group ¶ added in v0.3.0
func GenerateV2Group() UUID
GenerateV2Group produz um UUID de versão 2 no domínio Group usando o identificador de grupo do processo.
Em Windows a chamada de sistema devolve -1, e o identificador gravado fica sendo 0xFFFFFFFF.
func GenerateV2Person ¶ added in v0.3.0
func GenerateV2Person() UUID
GenerateV2Person produz um UUID de versão 2 no domínio Person usando o identificador de usuário do processo.
Em Windows a chamada de sistema devolve -1, e o identificador gravado fica sendo 0xFFFFFFFF.
func GenerateV3 ¶ added in v0.3.0
GenerateV3 produz um UUID de versão 3: o resumo MD5 do espaço de nomes concatenado com o nome, com versão e variante sobrescritas.
A geração é determinística e não usa entropia: o mesmo par espaço e nome sempre devolve o mesmo UUID, em qualquer máquina e a qualquer momento. Prefira a versão 5, que usa SHA-1.
func GenerateV4 ¶ added in v0.3.0
func GenerateV4() UUID
GenerateV4 produz um UUID de versão 4 usando o gerador padrão do pacote.
func GenerateV5 ¶ added in v0.3.0
GenerateV5 produz um UUID de versão 5: os 16 primeiros bytes do resumo SHA-1 do espaço de nomes concatenado com o nome, com versão e variante sobrescritas.
A geração é determinística e não usa entropia: o mesmo par espaço e nome sempre devolve o mesmo UUID, em qualquer máquina e a qualquer momento.
Example ¶
GenerateV5 é determinística: o mesmo par de espaço de nomes e nome sempre devolve o mesmo UUID. O valor abaixo é o vetor de teste da RFC 9562 para o espaço DNS.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
u := uuid.GenerateV5(uuid.NameSpaceDNS, []byte("www.example.com"))
fmt.Println(u)
}
Output: 2ed6657d-e927-568b-95e1-2665a8aea6a2
func GenerateV6 ¶ added in v0.3.0
func GenerateV6() UUID
GenerateV6 produz um UUID de versão 6 (RFC 9562): os mesmos campos do UUIDv1, porém com o tempo reordenado do bit mais significativo para o menos significativo, de modo que a ordenação lexicográfica coincide com a ordem cronológica.
Layout dos 16 bytes (big-endian):
bytes 0..3 : time_high ............... 32 bits altos do tempo bytes 4..5 : time_mid ................ 16 bits intermediários byte 6 : 0x6_ | time_low[11:8] ... versão(4) + topo dos 12 bits baixos byte 7 : time_low[7:0] ........... resto dos 12 bits baixos byte 8 : 10_ | clock_seq[13:8] ... variante(2) + topo da sequência byte 9 : clock_seq[7:0] .......... resto da sequência bytes 10..15: node ................... 48 bits de identificador de nó
A resolução do campo é de 100 nanossegundos, mais fina que a do UUIDv7 padrão. Ainda assim, prefira o UUIDv7 em bases novas: ele não expõe identificador de nó e é o recomendado pela RFC 9562.
Custo da ordem estrita: quando a geração é mais rápida que o tique de 100 nanossegundos, o relógio interno avança sozinho e o instante embutido fica à frente do relógio do sistema. Em rajadas longas esse adiantamento se acumula, na proporção de um tique por UUID. A RFC 9562 permite o comportamento, mas não conte com o carimbo de tempo de um UUIDv1 ou UUIDv6 como leitura fiel do relógio sob carga sustentada.
func GenerateV8 ¶ added in v0.3.0
GenerateV8 produz um UUID de versão 8: formato livre, reservado pela RFC 9562 para esquemas próprios de fornecedor.
Os 16 bytes informados são copiados como estão, e só os 6 bits de versão e variante são sobrescritos. Restam 122 bits sob controle do chamador. Nada aqui é interpretado como tempo, e a ordenação depende inteiramente do conteúdo fornecido.
func GenerateV8Random ¶ added in v0.3.0
func GenerateV8Random() UUID
GenerateV8Random produz um UUID de versão 8 aleatório usando o gerador padrão do pacote.
func Must ¶ added in v0.3.0
Must devolve u, ou entra em pânico se err não for nula. Serve para encadear com funções que devolvem par de valores.
func MustParse ¶ added in v0.3.0
MustParse interpreta um UUID em qualquer formato aceito por Parse e entra em pânico se a string for inválida.
Destina-se a constantes do próprio código, como espaços de nomes; nunca use com entrada vinda de fora do programa.
func New ¶ added in v0.3.0
func New() UUID
New produz um UUID de versão 4 com entropia criptográfica. Entra em pânico se a leitura de crypto/rand falhar, como uuid.New de origem.
func NewDCEGroup ¶ added in v0.3.0
NewDCEGroup produz um UUID de versão 2 no domínio Group. O erro é sempre nulo.
func NewDCEPerson ¶ added in v0.3.0
NewDCEPerson produz um UUID de versão 2 no domínio Person. O erro é sempre nulo.
func NewDCESecurity ¶ added in v0.3.0
NewDCESecurity produz um UUID de versão 2. O erro é sempre nulo.
func NewHash ¶ added in v0.3.0
NewHash produz um UUID baseado em nome com a função de resumo informada.
func NewRandom ¶ added in v0.3.0
NewRandom produz um UUID de versão 4 com entropia criptográfica. Devolve ErrEntropySource se a leitura falhar.
func NewRandomFromReader ¶ added in v0.3.0
NewRandomFromReader produz um UUID de versão 4 com 16 bytes lidos do leitor informado.
Monta um Generator descartável a cada chamada. Para uso repetido, prefira guardar o resultado de NewGeneratorWithReader.
func NewV7 ¶ added in v0.3.0
NewV7 produz um UUID de versão 7 padrão (Level1) com entropia criptográfica, como o pacote de origem. Devolve ErrEntropySource se a leitura falhar. Para velocidade máxima use Generate(Level1).
Para gravar precisão sub-milissegundo, use Generate com Level2 ou Level3.
func NewV7FromReader ¶ added in v0.3.0
NewV7FromReader produz um UUID de versão 7 com 16 bytes lidos do leitor informado.
Monta um Generator descartável a cada chamada. Para uso repetido, prefira guardar o resultado de NewGeneratorWithReader.
func Parse ¶ added in v0.3.0
Parse interpreta um UUID em qualquer um dos quatro formatos usuais:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx canônico, 36 caracteres
urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx URN, 45 caracteres
{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} entre chaves, 38 caracteres
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx hexadecimal cru, 32 caracteres
Maiúsculas e minúsculas são aceitas, inclusive no prefixo URN. Em caso de erro o UUID devolvido é sempre Nil.
Use FromString quando quiser aceitar somente o formato canônico.
Example ¶
Parse aceita as quatro formas usuais de escrever um UUID; todas produzem o mesmo valor.
package main
import (
"fmt"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
inputs := []string{
"0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff",
"{0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff}",
"urn:uuid:0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff",
"0192f7c51a2b7c3d8e4faabbccddeeff",
}
for _, in := range inputs {
u, err := uuid.Parse(in)
if err != nil {
fmt.Println("erro:", err)
continue
}
fmt.Println(u)
}
}
Output: 0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff 0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff 0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff 0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff
func ParseBytes ¶ added in v0.3.0
ParseBytes faz o mesmo que Parse a partir de uma sequência de bytes, sem converter para string e sem alocar.
func StringToBinary ¶
StringToBinary é um apelido explícito para FromString: converte a string canônica no binário de 128 bits.
func (UUID) AppendText ¶ added in v0.4.0
AppendText é AppendTo com a assinatura da interface encoding.TextAppender, introduzida no Go 1.24. O erro devolvido é sempre nulo.
A interface não é referenciada em lugar nenhum do pacote, então o método compila também nas versões anteriores, onde simplesmente não satisfaz interface alguma. Isso mantém o go.mod em 1.22.
func (UUID) AppendTo ¶ added in v0.4.0
AppendTo escreve a forma canônica de 36 bytes no fim de dst e devolve o slice estendido, como fazem as funções Append da biblioteca padrão.
É o caminho mais barato para serializar muitos identificadores: não aloca nada quando dst tem capacidade sobrando, enquanto String paga uma alocação por chamada. Reaproveite o mesmo buffer entre chamadas:
buf = u.AppendTo(buf[:0])
Passar nil é válido e faz a função alocar os 36 bytes.
func (UUID) Bytes ¶ added in v0.4.0
Bytes devolve uma cópia dos 16 bytes em ordem de rede. Alterar o resultado não afeta o UUID de origem.
Equivale a MarshalBinary sem o erro sempre nulo. Dentro do pacote do chamador, u[:] é mais barato e não copia, mas devolve um slice apoiado no próprio valor: use Bytes quando o destino guardar a referência.
Serve também para contornar uma armadilha de formatação: como UUID satisfaz fmt.Stringer, %x sobre um UUID formata a string canônica, não os bytes. fmt.Printf("%x", u.Bytes()) imprime os 32 dígitos esperados.
func (UUID) ClockSequence ¶ added in v0.3.0
ClockSequence extrai a sequência de relógio dos UUIDs de versão 1, 2 e 6. Nas versões 1 e 6 ela tem 14 bits. Na versão 2 o byte baixo da sequência é ocupado pelo domínio, portanto restam apenas os 6 bits altos (0 a 63). O segundo retorno é falso para as demais versões.
func (UUID) Compare ¶ added in v0.3.0
Compare ordena dois UUIDs pela sequência de bytes, devolvendo -1, 0 ou 1. Para UUIDs de versão 6 ou 7 a ordem coincide com a ordem cronológica.
Para simples igualdade não é preciso chamar nada: UUID é um vetor de bytes e aceita o operador de igualdade diretamente.
func (UUID) Domain ¶ added in v0.3.0
Domain extrai o domínio de um UUID de versão 2. O segundo retorno é falso para as demais versões.
func (UUID) GregorianTime ¶ added in v0.3.0
func (u UUID) GregorianTime() (GregorianTime, bool)
GregorianTime extrai o campo de tempo dos UUIDs de versão 1 e 6, em intervalos de 100 nanossegundos desde 15/10/1582.
O segundo retorno é falso para as demais versões, inclusive a 2: o UUIDv2 sacrifica os 32 bits baixos do tempo para guardar o identificador local, e o que sobra não é um carimbo utilizável.
func (UUID) ID ¶ added in v0.3.0
ID extrai o identificador local de um UUID de versão 2. O segundo retorno é falso para as demais versões.
func (UUID) IsValid ¶ added in v0.4.0
IsValid informa se o UUID tem a forma prevista pela RFC 9562: variante RFC (0b10) e número de versão entre 1 e 8.
Nil e Max são aceitos apesar de não carregarem versão nem variante: a RFC 9562 seção 5.9 e 5.10 os define como valores especiais válidos. Para distinguir esses dois casos, use IsZero e IsMax.
A verificação não é específica do UUIDv7: um UUIDv4 gerado em outro lugar também é válido. Para exigir a versão 7, compare Version com 7.
func (UUID) MarshalBinary ¶ added in v0.3.0
MarshalBinary devolve os 16 bytes do UUID em ordem de rede. Implementa encoding.BinaryMarshaler.
func (UUID) MarshalText ¶ added in v0.3.0
MarshalText devolve a representação canônica em texto, com 36 bytes. Implementa encoding.TextMarshaler, o que faz encoding/json gravar o UUID como string.
func (UUID) NodeID ¶ added in v0.3.0
NodeID extrai uma cópia dos 6 bytes de identificador de nó dos UUIDs de versão 1, 2 e 6. Devolve nulo para as demais versões.
func (*UUID) Scan ¶ added in v0.3.0
Scan lê um UUID vindo do banco de dados, implementando sql.Scanner.
Aceita:
nil — grava o UUID nulo
string — interpretado por Parse, em qualquer formato aceito;
a string vazia grava o UUID nulo, sem erro
[]byte — 16 bytes viram o valor binário; vazio grava o UUID nulo;
outro tamanho é texto
Texto vazio equivale a ausência de valor, como no pacote github.com/google/uuid: colunas de texto cujo valor padrão é a string vazia não devem falhar na leitura.
Em caso de erro o receptor não é alterado.
func (UUID) String ¶
String converte o UUID binário (16 bytes) na representação canônica em texto: 32 dígitos hexadecimais minúsculos agrupados como 8-4-4-4-12 e separados por hifens. Exemplo:
0192f7c5-1a2b-7c3d-8e4f-aabbccddeeff
A implementação escreve diretamente em um buffer de 36 bytes, sem alocações intermediárias, para ser barata em caminhos quentes.
Atenção: por UUID satisfazer fmt.Stringer, os verbos %x e %X do pacote fmt formatam esta string — devolvendo 72 caracteres com o hexadecimal do texto — e não os 16 bytes. Para imprimir os bytes, converta antes: fmt.Printf("%x", u[:]).
func (UUID) Timestamp ¶ added in v0.3.0
Timestamp devolve o instante de criação embutido no UUID, em UTC.
Funciona para as versões 1 e 6, com resolução de 100 nanossegundos, e para a versão 7, com resolução de milissegundo. Devolve falso para as versões que não carregam tempo — 2, 3, 4, 5 e 8.
Para recuperar também os microssegundos e nanossegundos gravados pelos níveis 2 e 3 desta biblioteca, use TimestampWithLevel.
func (UUID) TimestampWithLevel ¶ added in v0.3.0
TimestampWithLevel devolve o instante de criação de um UUIDv7 em UTC, reconstruindo a precisão sub-milissegundo gravada pelo nível informado.
O nível não pode ser deduzido do UUID, por isso precisa ser informado pelo chamador. Se algum campo lido estiver fora da faixa 0 a 999 — o que denuncia bits aleatórios, e não tempo — todos os campos sub-milissegundo são descartados e devolve-se apenas o milissegundo. No nível 3 os dois campos vêm da mesma geração: um rand_a fora da faixa prova que o topo de rand_b também é ruído, mesmo que caiba em 0 a 999 por acaso.
Devolve falso se o UUID não for de versão 7.
Example ¶
TimestampWithLevel reconstrói o instante com a precisão do nível informado. O nível não pode ser deduzido do UUID, por isso o chamador precisa dizê-lo.
package main
import (
"fmt"
"time"
uuid "github.com/patrickbrandao/go-loghub-uuid"
)
func main() {
// O mesmo UUID de Nível 3 usado em ExampleImportBinary.
u := uuid.MustParse("0192f7c5-1a2b-71c3-b930-0000aabbccdd")
ms, _ := u.Timestamp() // só o milissegundo, como qualquer UUIDv7
l3, _ := u.TimestampWithLevel(uuid.Level3)
fmt.Println(ms.Format(time.RFC3339Nano))
fmt.Println(l3.Format(time.RFC3339Nano))
}
Output: 2024-11-04T15:22:22.635Z 2024-11-04T15:22:22.635451915Z
func (UUID) URN ¶ added in v0.3.0
URN devolve a representação como URN da RFC 8141, ou seja, a string canônica prefixada por "urn:uuid:".
func (*UUID) UnmarshalBinary ¶ added in v0.3.0
UnmarshalBinary lê exatamente 16 bytes em ordem de rede. Implementa encoding.BinaryUnmarshaler.
Em caso de erro o receptor não é alterado.
func (*UUID) UnmarshalText ¶ added in v0.3.0
UnmarshalText lê a representação em texto, aceitando os mesmos quatro formatos de Parse. Implementa encoding.TextUnmarshaler.
Em caso de erro o receptor não é alterado.
func (UUID) Value ¶ added in v0.3.0
Value entrega o UUID ao banco de dados como a string canônica, implementando driver.Valuer.
Para gravar em coluna binária de 16 bytes, passe o valor fatiado pelo chamador em vez de confiar nesta conversão.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Pacote tests contém a suíte de testes funcionais, os benchmarks e utilitários de validação da biblioteca go-loghub-uuid.
|
Pacote tests contém a suíte de testes funcionais, os benchmarks e utilitários de validação da biblioteca go-loghub-uuid. |
|
benchmark-bulk
command
Comando benchmark-bulk gera 1.000.000 de UUIDv7 de cada nível e imprime um relatório de tempo e throughput.
|
Comando benchmark-bulk gera 1.000.000 de UUIDv7 de cada nível e imprime um relatório de tempo e throughput. |