{"id":13491049,"url":"https://github.com/oklog/ulid","last_synced_at":"2025-05-14T21:03:04.954Z","repository":{"id":37821145,"uuid":"75744278","full_name":"oklog/ulid","owner":"oklog","description":"Universally Unique Lexicographically Sortable Identifier (ULID) in Go","archived":false,"fork":false,"pushed_at":"2024-04-13T18:09:41.000Z","size":194,"stargazers_count":4692,"open_issues_count":8,"forks_count":173,"subscribers_count":41,"default_branch":"main","last_synced_at":"2025-05-01T21:38:57.066Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oklog.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-06T15:26:52.000Z","updated_at":"2025-05-01T16:37:12.000Z","dependencies_parsed_at":"2023-01-30T13:16:04.567Z","dependency_job_id":"c1386014-35c8-4525-811e-b520be0d3dd9","html_url":"https://github.com/oklog/ulid","commit_stats":{"total_commits":113,"total_committers":20,"mean_commits":5.65,"dds":"0.49557522123893805","last_synced_commit":"99f59762fe4431686af13a3dd4b190761b2ae908"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oklog%2Fulid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oklog%2Fulid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oklog%2Fulid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oklog%2Fulid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oklog","download_url":"https://codeload.github.com/oklog/ulid/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252837362,"owners_count":21811876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T19:00:53.131Z","updated_at":"2025-05-07T07:43:27.622Z","avatar_url":"https://github.com/oklog.png","language":"Go","readme":"# Universally Unique Lexicographically Sortable Identifier\n\n[![Project status](https://img.shields.io/github/release/oklog/ulid.svg?style=flat-square)](https://github.com/oklog/ulid/releases/latest)\n![Build Status](https://github.com/oklog/ulid/actions/workflows/test.yml/badge.svg)\n[![Go Report Card](https://goreportcard.com/badge/oklog/ulid?cache=0)](https://goreportcard.com/report/oklog/ulid)\n[![Coverage Status](https://coveralls.io/repos/github/oklog/ulid/badge.svg?branch=master\u0026cache=0)](https://coveralls.io/github/oklog/ulid?branch=master)\n[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go\u0026logoColor=white\u0026style=flat-square)](https://pkg.go.dev/github.com/oklog/ulid/v2)\n[![Apache 2 licensed](https://img.shields.io/badge/license-Apache2-blue.svg)](https://raw.githubusercontent.com/oklog/ulid/master/LICENSE)\n\nA Go port of [ulid/javascript](https://github.com/ulid/javascript) with binary format implemented.\n\n## Background\n\nA GUID/UUID can be suboptimal for many use-cases because:\n\n- It isn't the most character efficient way of encoding 128 bits\n- UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address\n- UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures\n- UUID v4 provides no other information than randomness which can cause fragmentation in many data structures\n\nA ULID however:\n\n- Is compatible with UUID/GUID's\n- 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)\n- Lexicographically sortable\n- Canonically encoded as a 26 character string, as opposed to the 36 character UUID\n- Uses Crockford's base32 for better efficiency and readability (5 bits per character)\n- Case insensitive\n- No special characters (URL safe)\n- Monotonic sort order (correctly detects and handles the same millisecond)\n\n## Install\n\nThis package requires Go modules.\n\n```shell\ngo get github.com/oklog/ulid/v2\n```\n\n## Usage\n\nULIDs are constructed from two things: a timestamp with millisecond precision,\nand some random data.\n\nTimestamps are modeled as uint64 values representing a Unix time in milliseconds.\nThey can be produced by passing a [time.Time](https://pkg.go.dev/time#Time) to\n[ulid.Timestamp](https://pkg.go.dev/github.com/oklog/ulid/v2#Timestamp),\nor by calling  [time.Time.UnixMilli](https://pkg.go.dev/time#Time.UnixMilli)\nand converting the returned value to `uint64`.\n\nRandom data is taken from a provided [io.Reader](https://pkg.go.dev/io#Reader).\nThis design allows for greater flexibility when choosing trade-offs, but can be\na bit confusing to newcomers.\n\nIf you just want to generate a ULID and don't (yet) care about details like\nperformance, cryptographic security, etc., use the\n[ulid.Make](https://pkg.go.dev/github.com/oklog/ulid/v2#Make) helper function.\nThis function calls [time.Now](https://pkg.go.dev/time#Now) to get a timestamp,\nand uses a source of entropy which is process-global,\n[pseudo-random](https://pkg.go.dev/math/rand), and\n[monotonic](https://pkg.go.dev/github.com/oklog/ulid/v2#LockedMonotonicReader).\n\n```go\nfmt.Println(ulid.Make())\n// 01G65Z755AFWAKHE12NY0CQ9FH\n```\n\nMore advanced use cases should utilize\n[ulid.New](https://pkg.go.dev/github.com/oklog/ulid/v2#New).\n\n```go\nentropy := rand.New(rand.NewSource(time.Now().UnixNano()))\nms := ulid.Timestamp(time.Now())\nfmt.Println(ulid.New(ms, entropy))\n// 01G65Z755AFWAKHE12NY0CQ9FH\n```\n\nCare should be taken when providing a source of entropy.\n\nThe above example utilizes [math/rand.Rand](https://pkg.go.dev/math/rand#Rand),\nwhich is not safe for concurrent use by multiple goroutines. Consider\nalternatives such as\n[x/exp/rand](https://pkg.go.dev/golang.org/x/exp/rand#LockedSource).\nSecurity-sensitive use cases should always use cryptographically secure entropy\nprovided by [crypto/rand](https://pkg.go.dev/crypto/rand).\n\nPerformance-sensitive use cases should avoid synchronization when generating\nIDs. One option is to use a unique source of entropy for each concurrent\ngoroutine, which results in no lock contention, but cannot provide strong\nguarantees about the random data, and does not provide monotonicity within a\ngiven millisecond. One common performance optimization is to pool sources of\nentropy using a [sync.Pool](https://pkg.go.dev/sync#Pool).\n\nMonotonicity is a property that says each ULID is \"bigger than\" the previous\none. ULIDs are automatically monotonic, but only to millisecond precision. ULIDs\ngenerated within the same millisecond are ordered by their random component,\nwhich means they are by default un-ordered. You can use\n[ulid.MonotonicEntropy](https://pkg.go.dev/github.com/oklog/ulid/v2#MonotonicEntropy) or\n[ulid.LockedMonotonicEntropy](https://pkg.go.dev/github.com/oklog/ulid/v2#LockedMonotonicEntropy)\nto create ULIDs that are monotonic within a given millisecond, with caveats. See\nthe documentation for details.\n\nIf you don't care about time-based ordering of generated IDs, then there's no\nreason to use ULIDs! There are many other kinds of IDs that are easier, faster,\nsmaller, etc. Consider UUIDs.\n\n## Commandline tool\n\nThis repo also provides a tool to generate and parse ULIDs at the command line.\n\n```shell\ngo install github.com/oklog/ulid/v2/cmd/ulid@latest\n```\n\nUsage:\n\n```shell\nUsage: ulid [-hlqz] [-f \u003cformat\u003e] [parameters ...]\n -f, --format=\u003cformat\u003e  when parsing, show times in this format: default, rfc3339, unix, ms\n -h, --help             print this help text\n -l, --local            when parsing, show local time instead of UTC\n -q, --quick            when generating, use non-crypto-grade entropy\n -z, --zero             when generating, fix entropy to all-zeroes\n```\n\nExamples:\n\n```shell\n$ ulid\n01D78XYFJ1PRM1WPBCBT3VHMNV\n$ ulid -z\n01D78XZ44G0000000000000000\n$ ulid 01D78XZ44G0000000000000000\nSun Mar 31 03:51:23.536 UTC 2019\n$ ulid --format=rfc3339 --local 01D78XZ44G0000000000000000\n2019-03-31T05:51:23.536+02:00\n```\n\n## Specification\n\nBelow is the current specification of ULID as implemented in this repository.\n\n### Components\n\n**Timestamp**\n- 48 bits\n- UNIX-time in milliseconds\n- Won't run out of space till the year 10889 AD\n\n**Entropy**\n- 80 bits\n- User defined entropy source.\n- Monotonicity within the same millisecond with [`ulid.Monotonic`](https://godoc.org/github.com/oklog/ulid#Monotonic)\n\n### Encoding\n\n[Crockford's Base32](http://www.crockford.com/wrmg/base32.html) is used as shown.\nThis alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.\n\n```\n0123456789ABCDEFGHJKMNPQRSTVWXYZ\n```\n\n### Binary Layout and Byte Order\n\nThe components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order).\n\n```\n0                   1                   2                   3\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                      32_bit_uint_time_high                    |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|     16_bit_uint_time_low      |       16_bit_uint_random      |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                       32_bit_uint_random                      |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                       32_bit_uint_random                      |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n```\n\n### String Representation\n\n```\n 01AN4Z07BY      79KA1307SR9X4MV3\n|----------|    |----------------|\n Timestamp           Entropy\n  10 chars           16 chars\n   48bits             80bits\n   base32             base32\n```\n\n## Test\n\n```shell\ngo test ./...\n```\n\n## Benchmarks\n\nOn a Intel Core i7 Ivy Bridge 2.7 GHz, MacOS 10.12.1 and Go 1.8.0beta1\n\n```\nBenchmarkNew/WithCryptoEntropy-8      2000000        771 ns/op      20.73 MB/s   16 B/op   1 allocs/op\nBenchmarkNew/WithEntropy-8            20000000      65.8 ns/op     243.01 MB/s   16 B/op   1 allocs/op\nBenchmarkNew/WithoutEntropy-8         50000000      30.0 ns/op     534.06 MB/s   16 B/op   1 allocs/op\nBenchmarkMustNew/WithCryptoEntropy-8  2000000        781 ns/op      20.48 MB/s   16 B/op   1 allocs/op\nBenchmarkMustNew/WithEntropy-8        20000000      70.0 ns/op     228.51 MB/s   16 B/op   1 allocs/op\nBenchmarkMustNew/WithoutEntropy-8     50000000      34.6 ns/op     462.98 MB/s   16 B/op   1 allocs/op\nBenchmarkParse-8                      50000000      30.0 ns/op     866.16 MB/s    0 B/op   0 allocs/op\nBenchmarkMustParse-8                  50000000      35.2 ns/op     738.94 MB/s    0 B/op   0 allocs/op\nBenchmarkString-8                     20000000      64.9 ns/op     246.40 MB/s   32 B/op   1 allocs/op\nBenchmarkMarshal/Text-8               20000000      55.8 ns/op     286.84 MB/s   32 B/op   1 allocs/op\nBenchmarkMarshal/TextTo-8             100000000     22.4 ns/op     714.91 MB/s    0 B/op   0 allocs/op\nBenchmarkMarshal/Binary-8             300000000     4.02 ns/op    3981.77 MB/s    0 B/op   0 allocs/op\nBenchmarkMarshal/BinaryTo-8           2000000000    1.18 ns/op   13551.75 MB/s    0 B/op   0 allocs/op\nBenchmarkUnmarshal/Text-8             100000000     20.5 ns/op    1265.27 MB/s    0 B/op   0 allocs/op\nBenchmarkUnmarshal/Binary-8           300000000     4.94 ns/op    3240.01 MB/s    0 B/op   0 allocs/op\nBenchmarkNow-8                        100000000     15.1 ns/op     528.09 MB/s    0 B/op   0 allocs/op\nBenchmarkTimestamp-8                  2000000000    0.29 ns/op   27271.59 MB/s    0 B/op   0 allocs/op\nBenchmarkTime-8                       2000000000    0.58 ns/op   13717.80 MB/s    0 B/op   0 allocs/op\nBenchmarkSetTime-8                    2000000000    0.89 ns/op    9023.95 MB/s    0 B/op   0 allocs/op\nBenchmarkEntropy-8                    200000000     7.62 ns/op    1311.66 MB/s    0 B/op   0 allocs/op\nBenchmarkSetEntropy-8                 2000000000    0.88 ns/op   11376.54 MB/s    0 B/op   0 allocs/op\nBenchmarkCompare-8                    200000000     7.34 ns/op    4359.23 MB/s    0 B/op   0 allocs/op\n```\n\n## Prior Art\n\n- [ulid/javascript](https://github.com/ulid/javascript)\n- [RobThree/NUlid](https://github.com/RobThree/NUlid)\n- [imdario/go-ulid](https://github.com/imdario/go-ulid)\n","funding_links":[],"categories":["UUID","开源类库","Go","Open source library","UUID 生成库","Utility","UUID`UUID 生成和操作库`","\u003ca name=\"Go\"\u003e\u003c/a\u003eGo"],"sub_categories":["查询语","UUID","实用程序/Miscellaneous","HTTP Clients","Utility/Miscellaneous","爬虫工具","Fail injection"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foklog%2Fulid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foklog%2Fulid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foklog%2Fulid/lists"}