Interesting comment, since v4 is the only version that provides the maximal random bits and is recommended for use as a primary key for non-correlated rows in several distributed databases to counter hot-spotting and privacy issues.
Edit: Context links for reference, these recommend UUIDv4:
https://www.cockroachlabs.com/docs/stable/uuid
https://docs.cloud.google.com/spanner/docs/schema-design#uui...
> To be clear, UUIDv8 is not a replacement for UUIDv4 (Section 5.4) where all 122 extra bits are filled with random data.
It's the same reason we use UTF-8. It's well supported. UUIDs are well supported by most languages and storage systems. You don't have to worry about endianness or serialization. It's not a thing you have to think about. It's already been solved and optimized.
Also mentioned on HN https://news.ycombinator.com/item?id=45323008
1. Users - your users table may not benefit by being ordered by created_at ( or uuid7 ) index because whether or not you need to query that data is tied to the users activity rather than when they first on-boarded.
2 Orders - The majority of your queries on recent orders or historical reporting type query which should benefit for a created_at ( or uuidv7 ) index.
Obviously the argument is then you're leaking data in the key, but my personal take is this is over stated. You might not want to tell people how old a User is, but you're pretty much always going to tell them how old an Order is.
It is heathwarming to see such mundane small tech bit making front page of HN when elsewhere is is debated whether programming as profession is dead or more broadly if AI will be enslaving humanity in the next decade. :)
If you’re tired of talking about AI, why did you post this?
In the past few weeks I've started opening neovim again and just writing code. It's still 50/50 with a Claude code instance, but fuck I don't feel a big productivity difference.
AI delivers the feeling of productivity and the ability to make endless PoCs. For some tasks it's actually good, of course, but writing high quality software by itself isn't one.
a = 1
assert a == 1
// many lines here where a is never used
assert a == 1
Yes AI test cases are awesome until you read what it's doing.
Especially when folks are trying to push % based test metrics and have types ( and thus they tests assert types where the types can't really be wrong ).
I use AI to write tests. Many of them the e2e fell into the pointless niche, but I was able to scope my API tests well enough to get very high hit rate.
The value of said API tests aren't unlimited. If I had to hand roll them, I'm not sure I would have written as many, but they test a multitude of 400, 401, 402, 403, and 404s, and the tests themselves have absolutely caught issues such as validator not mounting correctly, or the wrong error status code due to check ordering.
This is the same thing as picking a new smart programming language or package, or insisting that Dvorak layout is the only real way forward.
Personally I try to put as much distance to the modality discussion and get intimate with the substance.
But we're still required to go to the office, and talking to a computer on the open space is highly unwelcome
Watch as they stand at the watering hole, bored and listless. A sad look on their faces, knowing that now that Go has generics, all their joy has left their life. Like the dog that caught his tail, they are confused.
One looks at his friends as if to say, "Now what?"
Suddenly there is a noise.
All heads turn as they see the HN post about UUIDs.
One of the members pounces on it. "Why debate this when the entire industry is collapsing?"
No reply. Silence.
His peers give a half-hearted smile, as if to say, "Thanks for trying" but the truth is apparent. The joy of hating on programming languages is nil when AI is the only thing looking at code any more.
The Go hater returns to the waterhole. Defeated.
I see them crop up everywhere. IMO, they are decidedly human-unfriendly - particularly to programmers and database admins trying to debug issues. Too many digits to deal with, and they suck up too much column width in query results, spreadsheets, reports, etc.
I'm not saying they don't have a place (e.g. when you have a genuine need to generate unique identifiers across completely disconnected locations, and the id's will generally never need to be dealt with by a human). But in practice they've been abused to do everything under the sun (filenames, URL links, user id's, transaction numbers, database primary keys, etc). I almost want to start a website with a gallery of all the examples where they've been unsuitably shoehorned in when just a little more consideration would have produced something more humane.
For most common purposes, a conventional, centralized dispenser is better. Akin to the Take-A-Number reels you see at the deli. Deterministic randomization is a thing if you don't want the numbers to count sequentially. Prefixes, or sharding the ID space, is also a thing, if you need uniqueness across different latency boundaries (like disparate datacenters or siloed servers).
I've lost count of how many times I've seen a UUID generated when what the designer really should have done is just grab the primary key (or when that's awkward, the result of a GetNextId stored procedure) from their database.
This is an example of an unmaintained UUID library in a similar situation that is currently causing incompatibilities because they implemented the draft spec. and didn’t update when the RFC changed:
https://github.com/stevesimmons/uuid7/issues/1
Any Python developer using the uuid7 library is getting something that is incompatible with the UUIDv7 specification and other UUIDv7 implementations as a result. Developers who use the stdlib uuid package in Python 3.14+ and uuid7 as a fallback in older versions are getting different, incompatible behaviour depending upon which version of Python they are running.
This can manifest itself as a developer using UUIDv7 for its time-ordered property, deploying with Python <=3.13, upgrading to Python 3.14+ and discovering that all their data created with Python 3.13 sorts incorrectly when mixed with data created with Python 3.14+.
A UUID library that is not receiving updates is quite possibly badly broken and definitely warrants suspicion and closer inspection.
https://datatracker.ietf.org/doc/rfc9562/
The problem is not that it is a draft RFC, the problem is that the library is unmaintained with an unresponsive developer who is squatting the uuid7 package name. It’s the top hit for Python developers who want to use UUIDv7 for Python 3.13 and below.
If the library just existed as a correct implementation of the RFC without bugs or significant missing features, that would be one thing. But leaving features and bug fixes already committed to the repository unreleased for years because the maintainer hasn't cut a new release since 2024 is a bad sign.
The open issue in Google's repo about the package being malicious is not a good look. The community concluded it's a false positive. If the repo was maintained they'd confirm this and close the issue.
Maintaince is much more than RFC compliance, although the project hasn't met that bar either.
So, it makes sense for Go to introduce support for this as well.
Generally means it'll be going in unless something new comes up which alters people's thinking.
> Would like to point out how Go is rather the exception than the norm with regards to including UUID support in its standard library.
> C#: https://learn.microsoft.com/en-us/dotnet/api/system.guid.new...
> Java: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.htm...
> JavaScript: https://developer.mozilla.org/en-US/docs/Web/API/Crypto/rand...
> Python: https://docs.python.org/3/library/uuid.html
> Ruby: https://ruby-doc.org/stdlib-1.9.3/libdoc/securerandom/rdoc/S...
Is C# the language that gives the Go stdlib a run for its money? I haven't used it much. JS, Python, and Ruby, I have, quite a bit, and I have the sprawling requirements.txts and Gemfiles to prove it.
I asked the question I did upthread because, while there are a lot of colorable arguments about what Go did wrong, a complete and practical standard library where the standard library's functionality is the idiomatic answer to the problems it addresses is one of the things Go happens to do distinctively well. Which makes dunking on it for this UUID thing kind of odd.
For a short script, the standard "urllib.request" module [0] works pretty well, and is usually my first choice since it's always installed. For a larger program, I'll usually use a third-party module with more features/async support though, but I'll only do this if I'm using other third-party dependencies anyways.
> JS, Python, and Ruby, I have, quite a bit, and I have the sprawling requirements.txts and Gemfiles to prove it.
I checked the top 10 Go repositories on GitHub [1], and all but 1 of them have 30+ direct dependencies listed in their "go.mod" files (and many more indirect ones). Also, both C and JavaScript are well-known for their terrible standard libraries, yet out of all languages, JavaScript programs tend to use the most dependencies, while C programs tend to use the least. So I don't think that the number of dependencies that an average program in a given language uses says anything about the quality of that language's standard library.
That's not what happens in Golang.
But lots of programs (and most of the programs that I write) don't use any cryptography, and only have trivial networking requirements, and outside those areas, I'd argue that the Python standard library [0] has broader coverage, supports more features, and is better documented than the Go standard library [1].
The Go standard library is still pretty great though, and is well ahead of most other languages; I just personally think that it's a little worse than Python's. But if you mostly write networking/crypto code, I can easily see how you'd have the opposite opinion.
If you’re arguing as the grandparent did that Go regularly omits important packages from its standard library, then it’s not unreasonable to ask you for your idea of an exemplary stdlib.
And the more stuff you pack into the standard library the more expertise you need on the maintenance team for all these new libraries. And you don't want a standard library that is bad, because then people won't use it. And then you're stuck with the maintenance burden of code that no one uses. It's a big commitment to add something to a standard library.
So it's not that things just suddenly break.
For example they've removed asyncore, their original loop-based module before the async/await syntax existed. All the software from that era needs a total rewrite. Luckily in debian for now the module is provided as a .deb package so I didn't have to do the total rewrite.
edit: as usual on ycombinator, dowvotes for saying something factually true that can be easily verified :D
Not that it matters. I don't even think that there's a single piece of software in the world which would actually care about these bits rather than treating the whole byte array as opaque thing.
The fact that we're discussing this at all is a reasonable argument for using a library function.
For example Go has production ready HTTP server and client implementations in the standard library. But with Python, you have to use FastAPI or Flask, and requests or httpx. For SQL there's SQLAlchemy I guess and probably some other alternatives (my Python knowledge is not that great), whereas again with Go the abstraction is just in the standard library and you only include the driver for the specific database.
We use Renovate to manage dependency upgrades. It runs once a week. Every Python project has a handful or more dependency upgrades waiting every week, primarily due to the huge amount of dependencies and transitive dependencies in each project. The Go projects sometimes have one or two, but most of the time they're silent because there is nothing to upgrade (partly due to just having so few dependencies to begin with).
Also swiss tables were great addition to Go's native maps, but then again there are faster libraries that can give you 3x performance(in case of numeric keys).
UUIDs rarely get new versions. I don’t think it’d be too much to expect Go to stay relatively current on that.
Literal interview: concurrently hit these endpoints that returns json and sum the total of values returned. Handle any 400 or 500 level http errors.
Literal former Googlers and flubbing the interview. They would spend too much time setting up an IDE and project, not be sure how to handle errors, and unable to parse the json. We eventually added a skeleton java project and removed json from the api, allowing text only responses. I learned java people don't set up projects or deal with json. It is the only explanation
If added, keep the scope small: implement RFC 4122 v4 generation using crypto/rand.Read with correct version and variant bit handling, provide Parse and String, MarshalText and UnmarshalText, JSON Marshal and Unmarshal hooks, and database/sql Scanner and Valuer, and skip v1 MAC and time based generation by default because of privacy and cross-platform headaches.
But regardless of API ergonomics, I would love to have UUID v4 and v7 in the stdlib.
Having any structure whatsoever in them is pointless and stupid. UUIDs should be 128 buts of crypto.Rand() and nothing else.
Argh.
If just using random bytes, you still need to make decisions about how to serialize, put it in a URL, logging etc so you’re basically just inventing you’re own format anyway for a problem that’s already solved.
A uuidv4 is 15.25 bytes of payload encoded in 36 bytes (using standard serialisation), in a format which is not conducive to gui text selection.
You can encode 16 whole bytes in 26 bytes of easily selectable content by using a random source and encoding in base32, or 22 by using base58.
One example where UUIDs are useful is usage as primary keys in databases. The constraints provide benefits, such as global uniqueness across distributed systems.
I understand the defensiveness about implementing new features, and I understand the rationale to keep the core as small as possible. But come on, it's not like UUID is a new thing. As the opener already pointed out, UUID is essential in pretty much all languages for interoperability so it makes sense to have that in the standard language.
Anyways, I'm just happy we'll get generic methods after 10 years of debates, I suppose. Maybe we'll get an export keyword before another 10, too. Then CGo will finally be usable outside a single package without those overlapping autogenerated symbols...
If you want to see go-uniquie highschool debate club, look at Go team attitude to fixing logging, where community proposed multiple ways of solving it, Go team rejected all of them and then made massive navel-gazing post that could be summed up "well, there is multiple proposals THAT MEANS PEOPLE ARE UNSURE ON THE ISSUE so we won't do shit"
...then removed every question related to go logging (that were common in previous ones) in their yearly survey
However I would still advocate for it over C in scenarios easily covered by TinyGo and TamaGo.
The maintainers did the right thing by just saying "no."