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:
Yeah, I thought it was a strange comment, too. v7 is great when you explicitly need monotonicity, but encoded timestamps can expose information about your system. v4 is still very valid.
jandrewrogers 2 days ago [-]
I think "outdated" was a poor choice of words. It is a failure to meet application requirements, which has more to do with design than age. Every standardized UUID is expressly prohibited in some application contexts due to material deficiencies, including v4. That includes newer standards like v7 and v8.
In practice, most orgs with sufficiently large and complex data models use the term "UUID" to mean a pure 128-bit value that makes no reference to the UUID standard. It is not difficult to find yourself with a set of application requirements that cannot be satisfied with a standardized UUID.
The sophistication of our use case scenarios for UUIDs exceeds their original design assumptions. They don't readily support every operation you might want to do on a UUID.
zadikian 3 days ago [-]
Yeah v4 is the goto, and you only use something else if you have a very specific reason like needing rough ordering
jodleif 2 days ago [-]
Deterministic uuids is a very standard usecase
8organicbits 2 days ago [-]
You're talking about the hash-based UUIDv3/v5? I haven't found examples of those being used, but I'm curious.
Using MD5 or 122 bits of a SHA1 hash seems questionable now that both algorithms have known collisions. Using 122 bits of a SHA2/3 seems pretty limited too. Maybe if you've got trusted inputs?
buffalobuffalo 2 days ago [-]
I use these a lot. My favorite use case is templates, especially ones that were not initially planned in the architecture.
Let's say i have some entity like an "organization" that has data that spans several different tables. I want to use that organization as a "parent" in such a way where i can clone them to create new "child" organizations structured the same way they are. I also want to periodically be able to pull changes from the parent organization down into the child organization.
If the primary keys for all tables involved are UUIDs, I can accomplish this very easily by mapping all IDs in the relevant tables `id => uuid5(id, childOrgId)`. This can be done to all join tables, foreign keys, etc. The end result is a perfect "child" clone of the organization with all data relations still in place. This data can be refreshed from the parent organization any time simply by repeating the process.
eureka7 2 days ago [-]
I remember using them in a massive SQL query that needed to generate a GIS data set from multiple tables with an ungodly amount of JOINs and sub-queries to achieve ID stability. Don't ask :p
For those ~~curious~~ worried, no, this was not a security sensitive context.
zadikian 2 days ago [-]
Common one is if you want two structs deemed "equivalent" based on a few fields to get the same ID, and you're only concerned about accidental collision. There are valid use cases for that, but I've also seen it misused often.
v7 rough ordering also helps as a PK in certain sharded DBs, while others want random, or nonsharded ones usually just serial int.
8organicbits 2 days ago [-]
Have you seen UUIDv3/v5 used there though? I've seen lots of md5 historically and sha variants recently, but not the UUID approach.
zadikian 2 days ago [-]
Yeah, I've seen both 3 and 5 used, not just hashes in some custom format. That way it works with Postgres uuid type etc.
gzread 2 days ago [-]
If you want 128 bits of randomness why not use 128 bits of randomness? A random UUID presupposes the random number has to fit in UUID format.
da_chicken 2 days ago [-]
122 bits of randomness.
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.
gzread 2 days ago [-]
byte[16] is well supported by most languages and storage systems.
da_chicken 2 days ago [-]
Sure.
Now generate your random ID. Did you use a CSPRNG, or were your devs lazy and just used a PRNG? Are you doing that every time you're generating one of these IDs in any system that might need to communicate with your API? Or maybe they just generated one random number, and now they're adding 1 every time.
Now transfer it over a wire. Are you sure the way you're serializing it is how the remote system will deserialize it? Maybe you should use a string representation, since character transmission is a solved problem with UTF-8. OK, so who decides what that canonical representation is? How do we make it recognizable as an ID without looking like something that people should do arithmetic with?
It's not like random IDs were a new idea in 2002.
10000truths 2 days ago [-]
None of these are rocket-science problems, they're just standardization issues. You build a library with your generate_id/serialize_id/deserialize_id functions that work with a wrapper type, and tell your devs to use that library. UUID libraries are exactly that, except backed by an RFC.
da_chicken 2 days ago [-]
Of course they're not rocket science. But, the question here is, "Why don't you use random 16 bytes instead of a UUIDv4?" It's not a question about rocket science. The answer is still, "Because UUIDv4 is still a better way to do it." The UUID standard solves the second and third tier problems and knock-on effects you don't think about until you've run a system for awhile, or until you start adding multiple information systems that need to interact with the same data.
But, using UUIDv4 shouldn't be rocket science, either. UUID support should be built in to a language intended for web applications, database applications, or business applications. That's why you're using Go or C# instead of C. And Go is somewhat focused on micro-service architectures. It's going to need to serialize and deserialize objects regularly.
2 days ago [-]
jkrejcha 2 days ago [-]
> Now generate your random ID. Did you use a CSPRNG, or were your devs lazy and just used a PRNG?
There's nothing about UUIDs that need to make them cryptographically secure. Many programming language libraries don't (and some explicitly recommend against using them if you need cryptographically strong randomness).
foxglacier 1 days ago [-]
Not for security but to make sure you don't accidentally reuse the same seed. I've done that before when the PRNG seed was the time the application started and it turns out you can run multiple instances at the same time.
gzread 2 days ago [-]
How's your UUIDv4 generated?
> Are you sure the way you're serializing it is how the remote system will deserialize it?
It's 16 bytes. There's no serialization.
wredcoll 2 days ago [-]
What do they look like when I put it in a url?
2 days ago [-]
pphysch 2 days ago [-]
Use whatever encoding you want? Base64 is probably one of the most practical, but you're not obligated to use that.
bastawhiz 2 days ago [-]
UUIDs don't use base64
pphysch 1 days ago [-]
You can absolutely encode a UUID in base64, as you can any string of 128 bits.
bastawhiz 6 hours ago [-]
128 random bits in some random format aren't a uuid. 0.2ml of water isn't a raindrop. If I say "you can provide me with a uuid" and you give me a base64-encoded string, it's getting rejected by validation. If I say "this text needs to be a Unicode string" and you give me a base64-encoded Unicode string's byte array, it's not going to go well.
bastawhiz 2 days ago [-]
> There's no serialization.
Hex encoding with hyphens in the right spot isn't serialization?
2 days ago [-]
intelVISA 2 days ago [-]
Vibe endian
da_chicken 2 days ago [-]
Schrodinger's complement
efilife 2 days ago [-]
You are really making it seem like a huge problem. Generate random bytes, serialize to a string and store in a db. Done
A downvote tells me nothing. Please tell me what I'm missing, maybe I could learn something
bastawhiz 2 days ago [-]
> serialize to a string and store in a db
Ah, here we are. If it's just bytes, why store it as a string? Sixteen bytes is just a 128-bit integer, don't waste the space. So now the DB needs to know how to convert your string back to an integer. And back to a string when you ask for it.
"Well why not just keep it as an integer?"
Sure, in which base? With leading zeroes as padding?
But now you also need to handle this in JavaScript, where you have to know to deserialize it to a Bigint or Buffer (or Uint8Array).
UUIDs just mean you don't need to do any of this crap yourself. It's already there and it already works. Everything everywhere speaks the same UUIDs.
TomatoCo 2 days ago [-]
You have to generate random bytes with sufficient entropy to avoid collisions and you have to have a consistent way to serialize it to a string. There's already a standard for this, it's called UUID.
hamburglar 2 days ago [-]
It’s really not that complicated a problem. Don’t worry, you’ll certainly be able to solve all the problems yourself as you encounter them. What you end up with will be functionally equivalent to a proper UUID and will only have cost you man-months of pain, but then you will be able to truly understand the benefit of not spending your effort on easy problems that someone solved before you.
zadikian 2 days ago [-]
It's not a huge problem. Uuid adds convenience over reinventing that wheel everywhere. And some of those wheels would use the wrong random or hash or encoding.
(Downvote wasn't me)
bootsmann 3 days ago [-]
Really? Doesn’t v4 locally make the inserts into the B-Tree pretty messy? I was taught to use v7 because it allows writes to be a lot faster due to memory efficient paging by the kernel (something you lose with v4 because the page of a subsequent write is entirely random).
sintax 2 days ago [-]
https://www.thenile.dev/blog/uuidv7#why-uuidv7 has some details:
"
UUID versions that are not time ordered, such as UUIDv4 (described in Section 5.4), have poor database-index locality. This means that new values created in succession are not close to each other in the index; thus, they require inserts to be performed at random locations. The resulting negative performance effects on the common structures used for this (B-tree and its variants) can be dramatic.
".
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.
da_chicken 2 days ago [-]
It's memory and disk paging both.
There's also a hot spot problem with databases. That's the performance problem with autoincrement integers. If you are always writing to the same page on disk, then every write has to lock the same page.
Uuidv7 is a trade off between a messy b-tree (page splits) and a write page hot spot (latch contention). It's always on the right side of the b-tree, but it's spread out more to avoid hot spots.
That still doesn't mean you should always use v7. It does reversibly encode a timestamp, and it could be used to determine the rate that ids are generated (analogous to the German tank problem). If the uuidv7 is monotonic, then it's worse for this issue.
out_of_protocol 2 days ago [-]
v7 exposes creation date, and maybe you don't want that. So, depends on use-case
1f60c 2 days ago [-]
I think I read something once about using v7 internally and exposing v4 in your API.
talkin 2 days ago [-]
Or even an autoincrement int primary key internally. Depending on your scale and env etc, but still fits enough use cases.
matja 2 days ago [-]
In distributed databases I've worked with, there's usually something like a B-tree per key range, but there can be thousands of key ranges distributed over all the nodes in the cluster in parallel, each handling modifications in a LSM. The goal there is to distribute the storage and processing over all nodes equally, and that's why predictable/clustered IDs fail to do so well. That's different to the Postgres/MySQL scenario where you have one large B-tree per index.
pclmulqdq 2 days ago [-]
I believe current official guidance if you want a lot of random data is to use v8, the "user-defined" UUID. The use of v4 is strictly less flexible here.
8organicbits 2 days ago [-]
No, UUIDv8 offers 122 bits for vendor specific or experimental use cases. If you fill those bits randomly, you get the same amount of randomness as a v4. The spec is explicit that it does not replace v4 for random data use case.
> To be clear, UUIDv8 is not a replacement for UUIDv4 (Section 5.4) where all 122 extra bits are filled with random data.
Have you considered using two uuids for more randomness
arccy 2 days ago [-]
[flagged]
vzaliva 3 days ago [-]
A slow day in Go-news land? :)
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. :)
serial_dev 3 days ago [-]
It’s nice to have a break from AI FUD. It reminds me of a time when I could browse HN without getting anxiety immediately, because nowadays you can’t open a comment section without finding a comment about how you ngmi.
JimDabell 3 days ago [-]
Well fortunately you’re here to take what was a discussion completely unrelated to AI and drag it back around to AI again.
If you’re tired of talking about AI, why did you post this?
0x696C6961 3 days ago [-]
Man... I spent the last 6 months writing code using voice chat with multiple concurrent Claude code agents using an orchestration system because I felt like that was the new required skill set.
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.
cwbriscoe 3 days ago [-]
I just write my own code and then ask AI to find any issues and correct them if I feel it is good advice. What AI is amazing at is writing most of my test cases. Saves me a lot of time.
LtWorf 3 days ago [-]
I've seen tests doing:
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.
ownagefool 3 days ago [-]
To be fair, many human tests I've read do similar.
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.
alecbz 2 days ago [-]
It's good at writing/updating tedious test cases and fixtures when you're directing it more closely. But yes, it's not as great at coming up with what to test in the first place.
gzread 2 days ago [-]
I write assert(a==1) right before the line where a is assumed to be 1 (to skip a division by a) even if I know it's 1. Especially if I know it's 1!
porridgeraisin 3 days ago [-]
Yep. Especially for tests with mock data covering all sorts of extreme edge cases.
koakuma-chan 3 days ago [-]
Don't use AI for that, it doesn't know what your real data looks like.
porridgeraisin 3 days ago [-]
Majority of data in typical message-passing plumbing code are a combination of opaque IDs, nominal strings, few enums, and floats. It's mostly OK for these cases, I have found. Esp. in typed languages.
UqWBcuFx6NV4r 2 days ago [-]
lol. okay. neither do you.
tossandthrow 3 days ago [-]
There has always been a difference on modality and substance.
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.
p0w3n3d 3 days ago [-]
> voice chat ... required skill set
But we're still required to go to the office, and talking to a computer on the open space is highly unwelcome
gzread 2 days ago [-]
Right. If AI actually made you more productive, there would be more good software around, and we wouldn't have the METR study showing it makes you 20% slower.
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.
UqWBcuFx6NV4r 2 days ago [-]
Ah, yes. LLM-assisted development. That thing that is not at all changing, that thing that different people aren’t doing differently, and that thing that some people aren’t definitely way better at than others.
I swear that some supposedly “smart” people on this website throw their ability to think critically out the window when they want to weigh in on the AI culture war.
B-but the study!
I can way with certainty that:
1. LLM-assisted development has gotten significantly, materially better in the past 12 months.
2. I would be incredibly skeptical of any study that’s been designed, executed, analysed, written about, published, snd talked about here, within that period of time.
This is the equivalent of a news headline stating with “science says…”.
xerox13ster 2 days ago [-]
Nobody is interested in your piece of anecdata and asserting that something has gotten better without doing any studies on it, is the exact opposite of critical thinking.
You are displaying the exact same thing that you were complaining about.
stavros 3 days ago [-]
Really? The past two weeks I've been writing code with AI and feel a massive productivity difference, I ended up with 22k loc, which is probably around as many I'd have manually written for the featureset at hand, except it would have taken me months.
0x696C6961 2 days ago [-]
My work involves fixing/adding stuff in legacy systems. Most of the solutions AI comes up with are horrible. I've reverted back to putting problems on my whiteboard and just letting it percolate. I still let AI write most of the code once I know what I want. But I've stopped delegating any decision making to it.
stavros 2 days ago [-]
Ah, yeah, I can see that. It's not as good with legacy systems, I've found.
richard_todd 2 days ago [-]
Well at least for what I do, success depends on having lots of unit tests to lean on, regardless of whether it is new or existing code. AI plus a hallucination-free feedback loop has been a huge productivity boost for me, personally. Plus it’s an incentive to make lots of good tests (which AI is also good at)
MrBuddyCasino 3 days ago [-]
A lot of people‘s business model is to to capitalize on LLM anxiety to sell their PUA-tier courses.
VLM 2 days ago [-]
Its a small tech bit but a big architecture / management decision.
Basically, who runs golang?
The perfectionists are correct, UUIDs are awful and if there's a pile of standards that all have small problems the best thing you can do is make a totally new standard to add to the already too long list.
The in-the-trenches system software devs want this BAD. Check out https://en.wikipedia.org/wiki/Universally_unique_identifier#...
They want a library that flawlessly interops with everything on that list, ideally. Something you can trust and will not deprecate a function you need for live code and it just works. I admit a certain affinity to this perspective.
The cryptobros want to wait, there is some temporary current turmoil in UUID land. Not like "drama" but things are in flux and it would be horrible for golang to be stuck permanently supporting forever some interim thing that officially gets dropped (or worse, under scrutiny has a security hole or something, but for reverse compatibility with older/present golang would need permanent-ish reverse compatibility) Can't we just wait until 2027 or so? This is not the ideal time to set UUID policy in concrete. Just wait a couple more months or a year or two?
https://datatracker.ietf.org/doc/html/rfc9562
I think I covered the three groups that are fighting pretty accurately and at least semi fairly, I did make fun of the perfectionists a little but cut me a break everyone makes fun of those guys.
So, yeah, a "small technical bit" but its actually a super huge architectural / leadership / management decision.
I hope they get it correct, I love golang and have a side thing with tinygo. If you're doing something with microcontrollers that doesn't use networking and you're not locked in to a framework/rtos, just use tinygo its SO cool. Its just fun. I with tinygo had any or decent networking. Why would I need zephyr if I have go routines? Hmm.
I've been around the block a few times with UUID-alike situations and the worst thing they could decide is to swing to an extreme. They'll probably be OK this is not golangs first time around the block either.
It'll probably be OK. I hope.
sourcegrift 2 days ago [-]
I'm seeing deep technical stuff after months, so I'm happy!
3 days ago [-]
YesThatTom2 2 days ago [-]
Here we see Go haters in their natural habitat, the HN comment section.
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.
nightfly 2 days ago [-]
I think you're massively misreading the tone of the comment you're relying to
KingOfCoders 3 days ago [-]
One thing I love about Go, not fancy-latest-hype features, until the language collapses or every upgrade becomes a nightmare, just adding useful stuff and getting out of the way.
grey-area 2 days ago [-]
I know, I recently upgraded and skipped several releases without any issues with some large codebases.
The compatability guarantee is a massive win, so exciting to have a boring language to build on that doesn’t change much but just gradually gets better.
knorker 2 days ago [-]
Really? My experience is that of C, C++, Go, Python, and Rust, Go BY FAR breaks code most often. (except the Python 2->3 change)
Sure, most of that is not the compiler or standard library, but dependencies. But I'm not talking random opensource library (I can't blame the core for that), but things like protobuf breaking EVERY TIME. Or x/net, x/crypto, or whatever.
But also yes, from random dependencies. It seems that language-culturally, Go authors are fine with breaking changes. Whereas I don't see that with people making Rust crates. And multiple times I've dug out C++ projects that I have not touched in 25 years, and they just work.
grey-area 2 days ago [-]
The stdlib has been very very stable since the first release - I still use some code from Go 1.0 days which has not evolved much.
The x/ packages are more unstable yes, that's why they're outside stdlib, though I haven't personally noticed any breakage and have never been bitten by this. What breakage did you see?
I think protobuf is notorious for breaking (but more from user changes). I don't use it I'm afraid so have no opinion on that, though it has gone through some major revisions so perhaps that's what you mean?
I don't tend to use much third party code apart from the standard library and some x libraries (most libraries are internal to the org), I'm sure if you do have a lot of external dependencies you might have a different experience.
knorker 2 days ago [-]
Well, for C++ the backwards compatability is even better. Unless you're using `gets()` or `auto_ptr`, old C++ code either just continue to compile perfectly, or was always broken.
Sure, the Go standard library is in some sense bigger, so it's nice of them to not break that. But short of a Python2->3 or Perl5->6 migration, isn't that just table stakes for a language?
The only good thing about Go is that its standard library has enough coverage to do a reasonable number of things. The only good thing. But any time you need to step outside of that, it starts a bit-rotting timer that ticks very quickly.
> though [protobuf] has gone through some major revisions so perhaps that's what you mean?
No, it seems it's broken way more often than that, requiring manual changes.
grey-area 2 days ago [-]
But any time you need to step outside of that, it starts a bit-rotting timer that ticks very quickly.
This is not my experience with my own or third party code. I can't remember any regressions I experienced caused by code changes to the large stdlib at all in the last decade, and perhaps one caused by changes to a third party library (sendgrid, who changed their API with breaking changes, not really a Go problem).
A 'bit-rotting timer' isn't very specific or convincing, do you have examples in mind?
knorker 1 days ago [-]
>> But any time you need to step outside of that
"That" here refers to the standard library, so:
> I can't remember any regressions I experienced caused by code changes to the large stdlib at all in the last decade
I agree. But I'm saying it's a very low bar, since that's true for every language. But repeating myself I do acknowledge that Go in some senses has a bigger standard library. It's still just table stakes to not break stdlib.
> A 'bit-rotting timer' isn't very specific or convincing, do you have examples in mind?
I don't want to dox myself by digging up examples. But it seems that maybe half the time dependabot or something encourages me to bump versions on a project that's otherwise "done", I have to spend time adjusting to non backwards compatible changes.
This is not my experience at all in other languages. And you would expect it to be MORE common in languages where third party code is needed for many things that Go stdlib has built in, not less.
I've made and maintained opensource code continuously since years started with "19", and aside from Java Applets, everything else just continues to work.
> sendgrid, who changed their API with breaking changes, not really a Go problem
To repeat: "It seems that language-culturally, Go authors are fine with breaking changes".
grey-area 1 days ago [-]
I disagree about culture, I’d say that’s the culture of js.
For Go I’d say it’s the opposite and you have obviously been unlucky in your choices which you don’t want to talk about.
But it is not a universal experience. That is the only third party package with breaking changes I have experienced.
herewulf 2 days ago [-]
Isn't the x for experimental and therefore breaking API changes are expected?
knorker 1 days ago [-]
Sure.
To repeat: "It seems that language-culturally, Go authors are fine with breaking changes". I just chose x as examples of near-stdlib, as opposed to appearing to complain about some library made by some random person with skill issues or who had a reasonable opinion that since almost nobody uses the library, it's OK to break compat. Protobuf is another. (not to mention the GCP libraries, that both break and move URLs, and/or get deprecated for a rewrite every Friday)
The standard library not breaking is table stakes for a language, so I find it hard to give credit to Go specifically for table stakes.
And it's not like Go standard library is not a bit messy. As any library would be in order to maintain compatibility. E.g. net.Dialer has Timeout (and Deadline), but it also has DialContext, introduced later.
If the Go standard library had managed to maintain table stakes compatibility without collecting cruft, that'd be more impressive. But as those are contradictory requirements in practice, we shouldn't expect that of any language.
kayson 3 days ago [-]
Odd to me that the focus seems to be on the inactivity of Google's package when https://github.com/gofrs/uuid not only conforms to the newer standard but is actively maintained.
0x696C6961 3 days ago [-]
I get a kick out of publishing libs with no external deps. Regardless of reasoning, this change makes that easier.
ycombinatrix 3 days ago [-]
especially when they don't depend on libc.
da_chicken 3 days ago [-]
While the uuid package is actively maintained, it hasn't had a release since 2024. Indeed, there's an open issue from June 2025 asking about it: https://github.com/google/uuid/issues/194
rafram 3 days ago [-]
The RFC isn’t changing, is it?
JimDabell 3 days ago [-]
I’m not sure of the state of that particular library, but yes, the RFC has changed significantly. For instance, the UUIDv7 format changed from the earlier draft RFC resulting in incompatibilities.
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:
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.
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.
0x696C6961 3 days ago [-]
The problem here is a lack of namespaces. A problem the cargo bozos decided to duplicate
jrpelkonen 2 days ago [-]
Your point is completely invalidated by useless name calling. The people behind cargo are clearly accomplished and serious individuals, and even if you disagree with some of the choices, calling them bozos makes your whole argument unconvincing.
8organicbits 3 days ago [-]
RFC changes aside, the go community has been bit by unmaintained UUID libraries with security issues. Consider https://github.com/satori/go.uuid/issues/123 as a popular example.
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.
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.
PunchyHamster 3 days ago [-]
The proposal is 3 years old
thiht 2 days ago [-]
I don’t really care for Go supporting UUID generation, but UUIDs being a type from the stdlib will be invaluable, if they correctly implement the JSON, Text, database/sql and other standard marshallers/unmarshallers. We seriously need a standard UUID type across the ecosystem, and I’m glad it’s coming.
I did an analysis of Go dependencies[1] a few weeks ago and google/uuid is the 2nd most used dependency in the open source ecosystem, so its inclusion will be very impactful.
I would say the same for dec128. I would love a standard TYPE for dec128, with maybe zero cost std lib to transform it into a mutable uint128 or a zero cost conversion to struct{uint64,int64).
rkagerer 2 days ago [-]
That's great, but I abhor UUID's.
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.
3eb7988a1663 2 days ago [-]
At a prior job, there was an internal project code system for tracking billable hours or people assignment kind of thing. Everyone knew the codes of their projects. It was a six digit code, two letters and then four numbers: giving you some ~7 million point space. Company was ~100 years old and only had some 15k codes recorded in all history. The list of codes was manually updated once a quarter by an admin who might add another ten at a time.
Some chuckle head decided to replace the system with UUIDs. Now, they are no longer human memorable/readable/writable on paper/anything useful. Even better, they must have used some home grown implementation, because the codes were weirdly sequential. If you ever had to look at a dump of codes, the ids are almost identical minus a digit somewhere in the middle.
Destructive change that ruined a perfectly functional system.
staticassertion 2 days ago [-]
People should really just use integers.
It's funny how fast it is to just implement a counter and how much people rely on UUIDs to avoid it. If you already use postgres somewhere, just create a "counter" table for your namespace. You can easily count 10K-100k values per second or faster, with room to grow if you outscale that.
What do you get? The most efficient, compressible little integers you could ever want. You unlock data structures like roaring bitmaps/ treemaps. You cut memory to 25% depending on your cardinality (ie: you can use u16 or u32 in memory sometimes). You get insane compression benefits where you can get rows of these integers to take a few bits of data each after compression. You get faster hashmap lookups. It's just insane how this compounds into crazy downstream wins.
It is absolutely insane how little cost it is to do this and how many optimizations you unlock. But people somehow think that id generation will be their bottleneck, or maybe it's just easier to avoid a DB sometimes, or whatever, and so we see UUIDs everywhere. Although, agreed that most of the time you can just generate the unique id for data yourself.
In fairness, UUID is easier, but damn it wrecks performance.
teeray 2 days ago [-]
I just wish there was some human element to them so they were easier to talk about. Something like:
“Which row was it, ‘basketball fish’ or ‘cake potato’?
Of course, the words would need to be a checksum. As soon as you introduce them, nobody is looking at the hex again. Which is an improvement, since nobody is looking at all the hex now “it’s the one ending in ‘4ab’”.
tgv 2 days ago [-]
There's nothing stopping you from doing so. You don't have to use strict UUIDs. Their form rarely serves a real purpose anyway.
But for exposed values (document ids, customer ids, that kind of thing), it can be awkward if a patient's id is suddenly "CRANKY-...-FART".
kstrauser 2 days ago [-]
If I discovered that were my patient ID, I would laugh myself into unconsciousness and buy the staff a pizza.
VLM 2 days ago [-]
There's been a lot of historical work done in the past and I used NIST FIPS181 to implement this.
Note: FIPS181 was intended for passwords and I was using them as handy short human-readable record IDs as per your post. You probably shouldn't use FIPS181 for passwords in 2026 LOL.
Describing FIPS181 as pronounceable is optimistic. However its better than random text wrt human conversations. They start looking like mysterious assembly language mnemonics after awhile.
tomwphillips 2 days ago [-]
At $dayJob we use (user facing) IDs like this. Select a prefix then add a sufficient number of random alphanumeric characters for your use case.
foresto 2 days ago [-]
> Deterministic randomization is a thing if you don't want the numbers to count sequentially.
What are your favorite ways to approach this?
I think a maximal period linear feedback shift register might fit well.
2 days ago [-]
kittikitti 3 days ago [-]
Every time I've implemented UUID's it's for a database and something like PostgreSQL would handle it. Still glad to see this feature being worked on, I would have utilized a random string generator instead of the full battle tested UUID specification.
Generally means it'll be going in unless something new comes up which alters people's thinking.
0x696C6961 3 days ago [-]
Yes
jillesvangurp 3 days ago [-]
Kotlin also added RFC 9562 (which includes the new UUID versions) support to the standard library in version 2.3 recently. It's a multi platform implementation too so it works on native, wasm, jvm and js. I think it makes a lot of sense to default to that now that the IETF RFC has been out for a few years.
So, it makes sense for Go to introduce support for this as well.
MarekKnapek 2 days ago [-]
Is there a way to have benefits of both? Version 7 for better database clustering. And version 4 for complete randomness? So users can not inference nothing from the id? I have an idea: Use version 7 internally, then scramble it before sending to the user. Scrambling could be done by the database or by the server application. It could be as simple as XOR with some 128bit constant, or as resilient as AES encryption. Of course you also need to do unscrambling of IDs coming from users.
If privacy is the main concern (as it is in most usage of UUIDs) you could just encrypt the integer primary key instead with something like feistel and avoid the performance problems of UUIDs while still having opaque public identifiers.
malklera 2 days ago [-]
Wonder about the opinion of the maintainers of the Google package. Will they put it on maintenance mode or continue developing it like usual?
gethly 2 days ago [-]
Seems pointless. Go should focus on refactoring core libraries, especially net and http, for performance because nbio, gnet and others are kicking its ass. And that is sad, as third party libraries should never perform better than standard library.
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).
kbolino 2 days ago [-]
From nbio's README:
For regular connection scenarios, nbio's performance is inferior to the standard library due to goroutine affinity, lower buffer reuse rate for individual connections, and variable escape issues.
From gnet's README:
gnet and net don't share the same philosophy in network programming. Thus, building network applications with gnet can be significantly different from building them with net, and the philosophies can't be reconciled.
[...]
gnet is not designed to displace the Go net, but to create an alternative in the Go ecosystem for building performance-critical network services.
Frankly, I think it's unfair to argue that the net package isn't performant, especially given its goals and API surface.
However, the net/http package is a different story. It indeed isn't very performant, though one should be careful to understand that that assessment is on relative terms; net/http still runs circles around some other languages' standard approaches to HTTP servers.
A big part of why net/http is relatively slow is also down to its goals and API surface. It's designed to be easy to use, not especially fast. By comparison, there's fasthttp [1], which lives up to its name, but is much harder to work with properly. The goal of chasing performance at all costs also leads to questionable design decisions, like fiber [2], based on fasthttp, which achieves some of its performance by violating Go's runtime guarantee that strings are immutable. That is a wild choice that the standard library authors would/could never make.
STD is built on goroutines whereas these performance networking libraries are built on a main reactor loop. Hence the need for refactoring, not just tweaking.
Something like http/v2 and net/v2. I know gnet had(has?) issues wit implementing tls because how the entire STD is designed to work. At the time, it was a great piece of software, but by now, it is slow and outdated. A lot of progress has been made since in networking, parsing, serialization, atomics and so on.
2 days ago [-]
Mawr 2 days ago [-]
> And that is sad, as third party libraries should never perform better than standard library.
It's quite literally the opposite. The purpose of a stdlib is standardization, stability, and broad usefulness, not extreme performance. In fact, that can't be its purpose — you can only get max performance if you tune for your exact use case — but how could a stdlib that's by definition generic ever be able to do that?
> but then again there are faster libraries that can give you 3x performance(in case of numeric keys)
Yeah, exactly. If you can constrain your problem domain ("numeric keys only"), you can always squeeze out more performance than a generic algorithm can give you. Completely irrelevant as far as stdlib goes though.
gethly 1 days ago [-]
Standard library often has access to low level code that the user space does not. Hence why it must be the most performant code there is. Period. As for the maps, there is no reason why swiss maps must be used for every key type. Optimising the hashing for specific types makes a lot of sense and is a waste if not done.
sieep 2 days ago [-]
Cool! I love go and things like this will keep bringing me back :)
therealdrag0 3 days ago [-]
Golang lack of support for basic stuff like this is quite annoying.
tptacek 3 days ago [-]
What's the language you're thinking of that has more of these decisions fixed in the standard library? I know it's not Ruby, Python, Rust, or Javascript. Is it Java? I don't think this is something Elixir does better.
JimDabell 3 days ago [-]
Perhaps I’m misunderstanding, but the linked issue seems to address this directly:
> Would like to point out how Go is rather the exception than the norm with regards to including UUID support in its standard library.
You're answering the question of "which languages have UUIDs in their standard libraries" (Javascript is not one of them). That's not the question I'm asking. If you wrote a new Python program today that needed to make HTTP requests, would you rely on the stdlib, or would you pull in a dep? In a Java program, if you were encrypting files or blobs, stdlib or dep?
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.
gucci-on-fleek 3 days ago [-]
> If you wrote a new Python program today that needed to make HTTP requests, would you rely on the stdlib, or would you pull in a dep?
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.
Just claiming you'd use urllib is a concession. Yeah, I get it: for toy programs, you'd use the stdlib's HTTP.
That's not what happens in Golang.
gucci-on-fleek 3 days ago [-]
Fair enough, but the quality/breadth of the standard libraries is fairly topic-specific in Go (and all languages, really). There's a reason that you picked networking and crypto for your examples, since the Go standard library is indeed really strong here—I don't even like Go, but if I had to write a program that did lots of cryptography and networking, then Go would probably be my first choice.
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.
Like, at this point, I feel like we share premises. We disagree, but, fine, seems like a reasonable disagreement. A better one than how annoying it is that Golang lacks "basic stuff" like a standard UUID interface.
gzread 2 days ago [-]
Or a GUI framework
PunchyHamster 3 days ago [-]
[flagged]
gucci-on-fleek 3 days ago [-]
I gave that example to refute the point that having worked on projects in other languages with tons of third-party dependencies implies that those languages have poor standard libraries. I certainly didn't intend to imply that that means that Go has a poor standard library or that small Go projects often use hundreds of third-party dependencies like JavaScript projects tend to do.
Go's package management is actually one of its strongest points, so I think that it's unsurprising/good that some projects have lots of dependencies. But I still stand by the point that you shouldn't judge a language based on how many dependencies most programs written in it use.
(Except for JavaScript, where I have no problem judging it by the npm craziness :) )
tomhow 2 days ago [-]
Please don't post sneers and swipes like this on HN. The guidelines make it clear we're trying for much better than this.
No one is debating whether Go is missing a uuid package from its standard library; the debate is about whether this is indicative of a general trend with the Go standard library (as the gp claimed above).
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.
thayne 2 days ago [-]
I think the closest thing to an exemplary stdlin is rust's std. I think it strikes a good balance between being too small or too big. Unfortunately, what rust doesn't really have (yet) is a "blessed" set of libraries to supplement the stdlib.
The problems with a big "batteries included" standard library like go or python strives for, are that you will inevitably leave things out that at least some people consider "basic", like uuid, and parts of stdlib will probably have lower quality than third party libraries, like pythons urllib or gos log package, and it is constrained by needing to maintain backwards compatibility and being tied to the language's release cycle.
throwaway894345 2 days ago [-]
I didn’t have a strong opinion on standard library sizes until I tried Rust, but Rust was not a very pleasant experience because there were not standard packages or even consistent community advice for things as pervasive as error handling or async.
But I understand people have different opinions and that there will never be a standard library that appeases everyone. I don’t think “having a batteries included library” aims to appease everyone either. But mostly I just don’t understand the people who criticize Go for not having enough things in their standard library because Go’s standard library is one of the more useful (which may not be everyone’s ideal).
artimaeis 3 days ago [-]
My first, and primary, programming language was C# which includes probably too large a standard library. It was definitely a surprise to see how minimal/simple other standard libraries are!
jen20 3 days ago [-]
Like Python though, while the batteries are included, many of them are dead.
bigstrat2003 2 days ago [-]
But they're there. I would much rather have a stdlib option which isn't as good as the most popular third party solution, than not have an stdlib option at all. You can't always count on being able to install stuff from pypi, but you can always count on the stdlib being present.
LtWorf 3 days ago [-]
Yes because the formats and protocols they are for have changed so much right? -_-'
gzread 2 days ago [-]
Yes, and surrounding expectations like async. Urllib doesn't pool connections.
0x696C6961 3 days ago [-]
It begs the question, why don't these languages put out a v2 stdlib?
remus 3 days ago [-]
Broadly speaking, maintaining a big std lib is a huge amount of work, so it makes sense that a language team is conservative about adding new surface to a stb lib which they will then have to maintain for a long time.
PunchyHamster 3 days ago [-]
Why it is "huge amount of work" ? Do the code reliably breaks in every new python version ?
Philip-J-Fry 2 days ago [-]
The work involved in maintaining a standard library is things like bug fixes. A larger standard library (or multi versions) means there's more likely to be bugs. You also have performance improvements, and when new versions of the language come out which has features to improve performance, you will most likely want to go back through and refactor some code to take advantage of it. You will also want to go through and refactor to make code easier to maintain. All of this just gets harder with a larger surface.
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.
can3p 2 days ago [-]
Every library is a liability especially in terms of api. There are many example where the first take on a problem within a std lib was a bad choice and required a major overhaul. Once something is in standard library it’s literally impossible to take it back without breaking the world if you don’t control api consumers
LtWorf 3 days ago [-]
Yes, in python they break something at every release now. It's terrible. It mostly is because they remove modules from their standard library for no good reasons.
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
Hendrikto 2 days ago [-]
I think the downvotes are because you did not answer the question you replied to, and instead gave a pretty unrelated rant.
LtWorf 2 days ago [-]
I'm explaining that yes, code does break every new python version? Mostly because they touch the stdlib instead of just leaving it be.
akerl_ 2 days ago [-]
The thread is about the code in the std lib being a huge amount of work because the code in the std lib needs to be kept working with new language releases.
And then you answered about downstream code breakage totally outside the std lib.
What would that entail, just a package whitelist? A few renamed packages? In the python 3 transition they renamed urllib2 to just urllib, but now it's almost a dead battery too and you want to use requests.
isbvhodnvemrwvn 2 days ago [-]
Python had enough fun with 2 to 3 transition I think.
3eb7988a1663 2 days ago [-]
Honestly the problem was they did not go far enough. They hoped to have a minimal churn switch to avoid getting locked into bikeshedding for the rest of time. However, there was so little user user facing improvements that the required change hardly seemed worth porting. They also failed to initially offer any automatic porting tooling which could have increased adoption.
I will be forever mad that they did not use that as a breaking opportunity to namespace the standard library. Something like: `import std.io` so that other libraries can never conflict.
kbolino 2 days ago [-]
> They also failed to initially offer any automatic porting tooling which could have increased adoption.
Maybe it wasn't very good, but 2to3 was there from the start:
the idea of what 'batteries included' means has changed a lot in the past twenty years, and like most Go quirks , probably Google just didn't need <missing-things>.
tptacek 3 days ago [-]
Huh? The universal idiomatic answer to "how to use UUIDs in Go programs" for the past decade has been to pull in a Google dep.
throwaway894345 3 days ago [-]
Google is the author of the de facto uuid library in Go, google/uuid. I’m very curious what people think is an exemplary “batteries included” stdlib?
vbezhenar 3 days ago [-]
UUID is just array of 16 bytes or two 64-bit ints. Generating UUIDv4 is like few lines of code. Is that a big deal? I don't think so.
computomatic 3 days ago [-]
16 random bytes is not a valid UUIDv4. I don’t think it needs to be in the standard library, but implementing the spec yourself is also not the right choice for 99% of cases.
rollulus 3 days ago [-]
Well that depends on your luck, it could be a valid one about 1/16th of the time.
jasomill 2 days ago [-]
1/64, actually, because RFC-compliant (variant 1) UUIDv4 requires fixed values for both the version nibble and two bits of the variant nibble.
The fact that we're discussing this at all is a reasonable argument for using a library function.
3eb7988a1663 2 days ago [-]
While it might be invalid, will most libraries choke if you give them a pseudo UUIDv4?
efilife 1 days ago [-]
What do you mean? Are you talking about validation of UUIDs?
3eb7988a1663 1 days ago [-]
If you generate random bytes, which are unlikely to conform to the UUIDv4 spec, my guess is that most libraries will silently accept the id. That is, generating random bytes, will probably work just work.
efilife 1 days ago [-]
But what libraries are you talking about? What is their purpose?
rollulus 2 days ago [-]
Nice, thanks and I agree.
vbezhenar 2 days ago [-]
I didn't say about 16 random bytes. But you're almost there. You generate 16 random bytes and perform few bitwise operations to set version and variant bits correctly.
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.
groestl 3 days ago [-]
Let's call it a valid UUIDv0 - all bits randomized including the version bits :)
koakuma-chan 3 days ago [-]
What if I generate 16 random bytes and use that as id?
usrnm 3 days ago [-]
No problem, just don't call it UUID
danishanish 3 days ago [-]
I think it saves labor and eventual bug hunting to include these in a stdlib. We should not be expected to look up the UUIDv4 spec and make sure you’re following it correctly. This feels like exactly what reasonable encapsulation should be.
8organicbits 2 days ago [-]
I had a similar thought a while back. Looking at the code for existing UUID projects, issues they fixed, and in some cases the CVEs, is a good way to form a different opinion.
Razengan 2 days ago [-]
You can say this for everything that has built-in support.
vbezhenar 2 days ago [-]
Some things are actually hard to implement. I'd spent a lot of time trying to implement concurrent hashmap, for example. UUID is not one of these things.
foresto 2 days ago [-]
What stuff do you have in mind?
I was disappointed by Go's poor support for human-focused logging. The log module is so basic that one might as well just use Printf. The slog module technically offers a line-based handler, but getting a traditional format out of it is painful at best, it lacks features that are common elsewhere, and it's somehow significantly slower than the json handler. I can only guess that it was added as an afterthought, by someone who doesn't normally do that kind of logging.
To be fair, I suppose this might make sense if Go is intended only for enterprisey environments. I often do projects outside of those environments, though, so I ended up spending a lot of time on a side quest to build what I expected to be built-in.
I haven't explored enough of the stdlib yet to know what else that I might expect is not there. If you have a wish list, would you care to share it?
p0w3n3d 3 days ago [-]
It makes you look on GitHub for implementations, which later can be hijacked and used for malicious reasons
catlifeonmars 3 days ago [-]
What other basic stuff are you thinking of?
patrickmcnamara 3 days ago [-]
I'd love to see proper WebSocket support, and JWTs.
catlifeonmars 1 days ago [-]
What other languages have web socket support or JWT validation as part of their standard libraries?
I don’t disagree with you btw. JWT signing/verification and JWK support is especially something I would prefer had first class implementations. (I’m much less concerned with JWT parsing, which is trivial).
You can't comment like this on Hacker News, no matter what you're replying to. If you wouldn't mind reviewing https://news.ycombinator.com/newsguidelines.html and taking the intended spirit of the site more to heart, we'd be grateful.
LtWorf 3 days ago [-]
Open the python documentation if you're curious of why people are downvoting you.
HendrikHensen 2 days ago [-]
I cannot identify with this at all. We have Python and Go applications in production, and for Go the vibe is mostly "standard library plus a few dependencies" (e.g. SQL driver, opentelemetry) whereas with Python it's mostly "we need a dozen libraries just to get something done".
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).
LtWorf 2 days ago [-]
Seems to me you overcomplicate your python dependencies on purpose and then complain that they are complicated.
I've never seen a go program that is more than hello world that has only 1 or 2 dependencies in my whole professional life.
2 days ago [-]
sethammons 3 days ago [-]
I don't buy this for one moment. Python and breaking changes are lovers. Nobody I have ever worked with builds or tries to build stdlib python. Most Go devs to pride themselves on minimal dependencies.
LtWorf 2 days ago [-]
Honestly, I don't understand what you wrote so I cannot reply.
2 days ago [-]
cookiengineer 3 days ago [-]
Every time I read these types of Go issues, I think I am reading a writeup of a highschool debate club. It's like there is debate just for the sake of debate.
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...
tptacek 3 days ago [-]
It's an open Github issues thread. What do you expect?
pjmlp 3 days ago [-]
Which is why I changed from being on Gonuts during pre-1.0 days to only touch Go if I really have to.
However I would still advocate for it over C in scenarios easily covered by TinyGo and TamaGo.
PunchyHamster 3 days ago [-]
I mean that's pretty common in most OSS projects just because you have free entry to the debate.
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
silisili 3 days ago [-]
It's called bikeshedding. It's highly annoying, but unfortunately every public mailing list or tracker is prone to it.
The maintainers did the right thing by just saying "no."
knodi 2 days ago [-]
Go is often the best part of my work day.
jeffrallen 3 days ago [-]
Am I the only one who hates UUIDs and doesn't see the point of them?
Having any structure whatsoever in them is pointless and stupid. UUIDs should be 128 buts of crypto.Rand() and nothing else.
Argh.
sevg 3 days ago [-]
UUIDs are recognizable, have a version field, can be sorted in the case of UUIDv7, a standardized format means easy interoperability (eg, encoding, validation, serialization etc), and databases can optimize storage and efficiency when using a native UUID type.
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.
masklinn 3 days ago [-]
That the problem is already solved does not mean the solution is good. Or that you can’t solve it better.
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.
3 days ago [-]
chuckadams 2 days ago [-]
Has anything post-dating the DCE-RPC era ever looked at the version of a UUID?
HendrikHensen 2 days ago [-]
Why the hate though? Is someone forcing you to use them against your will? If you need 128 bits of crypto.Rand() for your usecase, you can just use that right?
whateveracct 3 days ago [-]
I treat UUIDv4s as 128 random bits and it triggers ppl.
gzread 2 days ago [-]
It needs several non-random bits to mark it as a v4 or it's not a uuidv4
masklinn 3 days ago [-]
To be fair that’s literally just a waste of resources. If you want 128 random bits just get 128 random bits from the underlying source, unless your host langage is amazingly deficient it’s just as easy.
fragmede 3 days ago [-]
they should be prefixed with something human readable so you can tell a service bot api key from a human developer api key or whatever.
PunchyHamster 3 days ago [-]
hahahaha as if humans wouldn't just give their hey to the bot
sethammons 2 days ago [-]
That misses the point. The point is for easy validation that the key was generated appropriately. Many api keys have a standard prefix for just this reason. It especially helps on documentation where the key name might be confused with the value: "your key starts with hnkey-"
efilife 3 days ago [-]
I hate UUIDv4, don't care about the rest. UUIDv4 is just random bytes with hyphens inserted in random places and some bytes reserved to indicate that this is in fact a UUID. This is wasteful and stupid
matja 3 days ago [-]
You aren't supposed to store the hyphens, and that's the same for all versions.
efilife 3 days ago [-]
What if I want an ID in the URL? Parse it back and forth? And what if for example, nodejs's UUID api only gives me the string representation of the ID?
matja 3 days ago [-]
To minimize the storage space while having a URL-safe representation, yeah you'd want to serialise/deserialise on the boundary of presenting it to API consumers. I think the same for any ID that has an efficient binary representation as well as needing to represent it in ASCII.
Dylan16807 2 days ago [-]
Is reserving 6 bits really that bad?
You can use different encodings based on context, just like with a random blob of bytes.
beart 3 days ago [-]
UUIDs aren't random by design, and the structure is not pointless. Calling something you don't understand "stupid" is probably not a good approach to life.
One example where UUIDs are useful is usage as primary keys in databases. The constraints provide benefits, such as global uniqueness across distributed systems.
masklinn 3 days ago [-]
The global uniqueness of a uuid v4 is the global uniqueness of pulling 122 bits from a source of entropy. Structure has nothing to do with it, and pulling 128 bits from the same source is strictly (if not massively) superior at that.
beart 2 days ago [-]
I stand corrected. I was thinking of the sequential nature of uuid 7, or SQL servers sequential id.
waynesonfire 3 days ago [-]
what a bunch of drama in the comments.
azinman2 3 days ago [-]
It’s kind of ridiculous to argue against UUID being part of the standard package for a language largely aimed at servers. At that point why even have any crypto functions or any of the bigger stuff it already has if the argument is 3rd party libs are enough?
tptacek 3 days ago [-]
UUIDv7 didn't mature until long after the Go standard library was mostly settled. By that point, there was already an idiomatic 3p dep for UUIDs (the Google package), and as you can see from the thread, there were arguments in favor of keeping it 3p (it can be updated on an arbitrary cadence, unlike the stdlib).
azinman2 3 days ago [-]
They could have implemented the other types of uuid generation, as well as having the standard type. Then evolve.
UUIDs rarely get new versions. I don’t think it’d be too much to expect Go to stay relatively current on that.
vips7L 3 days ago [-]
People are weird. A few days ago someone on /r/Java was arguing that a basic JSON parser shouldn’t be in the standard library.
sethammons 3 days ago [-]
Anecdote: about 8 years ago, I was interviewing hundreds of candidates for a non-java shop but you could interview in java if desired. One java dev ever was able to figure out parsing json with ease. Every single other java interview the person struggled with json. It was weird.
gzread 2 days ago [-]
You mean he could read it or he could write a parser or he could use a dependency?
sethammons 2 days ago [-]
Use a dependency. It was a wild pattern that still confuses me years later.
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
fl0ki 2 days ago [-]
"Former Googlers" were probably used to using protobuf so they could get from a function call straight out to a struct of the right schema. It's one level of abstraction higher and near-universal in Google, especially in internal-to-internal communication edges.
I don't think it's a strong hiring signal if they weren't already familiar with APIs for (de)serialization in between, because if they're worth anything then they'll just pick that up from documentation and be done with it.
8organicbits 2 days ago [-]
The question evaluates different skills when you solve it in Java. If you allowed XML, you'd see Java candidates reach for the standard library, as it has a built-in XML parser. Using plain text responses was a good fix, as the candidate can focus on concurrency, networking, and error handling, which is probably what you were trying to assess.
vips7L 2 days ago [-]
In my experience it’s Googler’s not Java people. All of my friends at Google tell me how everything is already set up for them.
a57721 2 days ago [-]
You mention it was 8 years ago, at that point a typical Java dev would be already using Spring Boot for requests and deserializing JSON to POJOs (with Jackson under the hood).
iJohnDoe 2 days ago [-]
> interviewing hundreds of candidates
For one position? To fill a department or company?
hrmtst93837 3 days ago [-]
Adding UUID to the standard library is defensible for a server-focused language, but making it part of the stdlib binds maintainers to long-term compatibility and support, so the debate should focus on API surface and long term maintenance rather than whether third-party packages exist.
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.
materielle 2 days ago [-]
I would really urge everyone to actually engage in the arguments people are making.
Go’s core design philosophy is stability. This means backwards compatibility forever. But really, even more than that. The community is largely against “v2” libraries. After the first version is introduced, Go devs trend towards stability, live with its flaws, and are super hesitant to fix things with a “v2”.
There have been exceptions. After 20 years of the frankly horrible json library, a v2 one is in the works.
Most of the uuid concerns come from a place of concern. After the api is added to the standard library, it will be the canonical api forever.
There are surely pros and cons to this design philosophy. I just don’t understand why people who disagree with Go’s core goals don’t just use a different language? Sorry to take a jab here, but are we really short on programming languages that introduce the wrong v1 api, so then the language ends up with codebases that depend on v1, v2, and v3? (Looking at you Java, Python, and C#)
Basically one guy having a fit when people disagreed with him.
fractorial 3 days ago [-]
It would appear that person and OP are one in the same.
rednafi 2 days ago [-]
Damn. I missed that. But yeah OP didn't take it well when people poked hole into his proposed API.
But regardless of API ergonomics, I would love to have UUID v4 and v7 in the stdlib.
arccy 2 days ago [-]
maybe the OP is trying but failing to drum up support for his unergonomic api proposal
throwaway894345 3 days ago [-]
Welcome to literally any Go thread.
ollybrinkman 2 days ago [-]
[flagged]
casey2 2 days ago [-]
UUIDs are one of those useless things standards people create so they can plop it in other standards. They don't, have never and can never solve a real problem, only hypothetical meta problems. That Go team probably sees UUID v7 and LOL'd their underpants off, you couldn't get it right the first 6 times? GTFO
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...
In practice, most orgs with sufficiently large and complex data models use the term "UUID" to mean a pure 128-bit value that makes no reference to the UUID standard. It is not difficult to find yourself with a set of application requirements that cannot be satisfied with a standardized UUID.
The sophistication of our use case scenarios for UUIDs exceeds their original design assumptions. They don't readily support every operation you might want to do on a UUID.
Using MD5 or 122 bits of a SHA1 hash seems questionable now that both algorithms have known collisions. Using 122 bits of a SHA2/3 seems pretty limited too. Maybe if you've got trusted inputs?
Let's say i have some entity like an "organization" that has data that spans several different tables. I want to use that organization as a "parent" in such a way where i can clone them to create new "child" organizations structured the same way they are. I also want to periodically be able to pull changes from the parent organization down into the child organization.
If the primary keys for all tables involved are UUIDs, I can accomplish this very easily by mapping all IDs in the relevant tables `id => uuid5(id, childOrgId)`. This can be done to all join tables, foreign keys, etc. The end result is a perfect "child" clone of the organization with all data relations still in place. This data can be refreshed from the parent organization any time simply by repeating the process.
For those ~~curious~~ worried, no, this was not a security sensitive context.
v7 rough ordering also helps as a PK in certain sharded DBs, while others want random, or nonsharded ones usually just serial int.
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.
Now generate your random ID. Did you use a CSPRNG, or were your devs lazy and just used a PRNG? Are you doing that every time you're generating one of these IDs in any system that might need to communicate with your API? Or maybe they just generated one random number, and now they're adding 1 every time.
Now transfer it over a wire. Are you sure the way you're serializing it is how the remote system will deserialize it? Maybe you should use a string representation, since character transmission is a solved problem with UTF-8. OK, so who decides what that canonical representation is? How do we make it recognizable as an ID without looking like something that people should do arithmetic with?
It's not like random IDs were a new idea in 2002.
But, using UUIDv4 shouldn't be rocket science, either. UUID support should be built in to a language intended for web applications, database applications, or business applications. That's why you're using Go or C# instead of C. And Go is somewhat focused on micro-service architectures. It's going to need to serialize and deserialize objects regularly.
There's nothing about UUIDs that need to make them cryptographically secure. Many programming language libraries don't (and some explicitly recommend against using them if you need cryptographically strong randomness).
> Are you sure the way you're serializing it is how the remote system will deserialize it?
It's 16 bytes. There's no serialization.
Hex encoding with hyphens in the right spot isn't serialization?
A downvote tells me nothing. Please tell me what I'm missing, maybe I could learn something
Ah, here we are. If it's just bytes, why store it as a string? Sixteen bytes is just a 128-bit integer, don't waste the space. So now the DB needs to know how to convert your string back to an integer. And back to a string when you ask for it.
"Well why not just keep it as an integer?"
Sure, in which base? With leading zeroes as padding?
But now you also need to handle this in JavaScript, where you have to know to deserialize it to a Bigint or Buffer (or Uint8Array).
UUIDs just mean you don't need to do any of this crap yourself. It's already there and it already works. Everything everywhere speaks the same UUIDs.
(Downvote wasn't me)
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.
There's also a hot spot problem with databases. That's the performance problem with autoincrement integers. If you are always writing to the same page on disk, then every write has to lock the same page.
Uuidv7 is a trade off between a messy b-tree (page splits) and a write page hot spot (latch contention). It's always on the right side of the b-tree, but it's spread out more to avoid hot spots.
That still doesn't mean you should always use v7. It does reversibly encode a timestamp, and it could be used to determine the rate that ids are generated (analogous to the German tank problem). If the uuidv7 is monotonic, then it's worse for this issue.
> To be clear, UUIDv8 is not a replacement for UUIDv4 (Section 5.4) where all 122 extra bits are filled with random data.
https://www.rfc-editor.org/rfc/rfc9562.html#section-5.8-2
> UUIDv8's uniqueness will be implementation specific and MUST NOT be assumed.
Here's a spec compliant UUIDv8 implementation I made that doesn't produce unique IDs: https://github.com/robalexdev/uuidv8-xkcd-221
So, given a spec-compliant UUIDv4 you can assume it is unique, but you'd need out-of-band information to make the same assumption about a UUIDv8.
I wrote much more in a blog post: https://alexsci.com/blog/uuid-oops/
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.
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
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.
I can way with certainty that: 1. LLM-assisted development has gotten significantly, materially better in the past 12 months.
2. I would be incredibly skeptical of any study that’s been designed, executed, analysed, written about, published, snd talked about here, within that period of time.
This is the equivalent of a news headline stating with “science says…”.
You are displaying the exact same thing that you were complaining about.
Basically, who runs golang?
The perfectionists are correct, UUIDs are awful and if there's a pile of standards that all have small problems the best thing you can do is make a totally new standard to add to the already too long list.
The in-the-trenches system software devs want this BAD. Check out https://en.wikipedia.org/wiki/Universally_unique_identifier#... They want a library that flawlessly interops with everything on that list, ideally. Something you can trust and will not deprecate a function you need for live code and it just works. I admit a certain affinity to this perspective.
The cryptobros want to wait, there is some temporary current turmoil in UUID land. Not like "drama" but things are in flux and it would be horrible for golang to be stuck permanently supporting forever some interim thing that officially gets dropped (or worse, under scrutiny has a security hole or something, but for reverse compatibility with older/present golang would need permanent-ish reverse compatibility) Can't we just wait until 2027 or so? This is not the ideal time to set UUID policy in concrete. Just wait a couple more months or a year or two? https://datatracker.ietf.org/doc/html/rfc9562
I think I covered the three groups that are fighting pretty accurately and at least semi fairly, I did make fun of the perfectionists a little but cut me a break everyone makes fun of those guys.
So, yeah, a "small technical bit" but its actually a super huge architectural / leadership / management decision.
I hope they get it correct, I love golang and have a side thing with tinygo. If you're doing something with microcontrollers that doesn't use networking and you're not locked in to a framework/rtos, just use tinygo its SO cool. Its just fun. I with tinygo had any or decent networking. Why would I need zephyr if I have go routines? Hmm.
I've been around the block a few times with UUID-alike situations and the worst thing they could decide is to swing to an extreme. They'll probably be OK this is not golangs first time around the block either.
It'll probably be OK. I hope.
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.
The compatability guarantee is a massive win, so exciting to have a boring language to build on that doesn’t change much but just gradually gets better.
Sure, most of that is not the compiler or standard library, but dependencies. But I'm not talking random opensource library (I can't blame the core for that), but things like protobuf breaking EVERY TIME. Or x/net, x/crypto, or whatever.
But also yes, from random dependencies. It seems that language-culturally, Go authors are fine with breaking changes. Whereas I don't see that with people making Rust crates. And multiple times I've dug out C++ projects that I have not touched in 25 years, and they just work.
The x/ packages are more unstable yes, that's why they're outside stdlib, though I haven't personally noticed any breakage and have never been bitten by this. What breakage did you see?
I think protobuf is notorious for breaking (but more from user changes). I don't use it I'm afraid so have no opinion on that, though it has gone through some major revisions so perhaps that's what you mean?
I don't tend to use much third party code apart from the standard library and some x libraries (most libraries are internal to the org), I'm sure if you do have a lot of external dependencies you might have a different experience.
Sure, the Go standard library is in some sense bigger, so it's nice of them to not break that. But short of a Python2->3 or Perl5->6 migration, isn't that just table stakes for a language?
The only good thing about Go is that its standard library has enough coverage to do a reasonable number of things. The only good thing. But any time you need to step outside of that, it starts a bit-rotting timer that ticks very quickly.
> though [protobuf] has gone through some major revisions so perhaps that's what you mean?
No, it seems it's broken way more often than that, requiring manual changes.
This is not my experience with my own or third party code. I can't remember any regressions I experienced caused by code changes to the large stdlib at all in the last decade, and perhaps one caused by changes to a third party library (sendgrid, who changed their API with breaking changes, not really a Go problem).
A 'bit-rotting timer' isn't very specific or convincing, do you have examples in mind?
"That" here refers to the standard library, so:
> I can't remember any regressions I experienced caused by code changes to the large stdlib at all in the last decade
I agree. But I'm saying it's a very low bar, since that's true for every language. But repeating myself I do acknowledge that Go in some senses has a bigger standard library. It's still just table stakes to not break stdlib.
> A 'bit-rotting timer' isn't very specific or convincing, do you have examples in mind?
I don't want to dox myself by digging up examples. But it seems that maybe half the time dependabot or something encourages me to bump versions on a project that's otherwise "done", I have to spend time adjusting to non backwards compatible changes.
This is not my experience at all in other languages. And you would expect it to be MORE common in languages where third party code is needed for many things that Go stdlib has built in, not less.
I've made and maintained opensource code continuously since years started with "19", and aside from Java Applets, everything else just continues to work.
> sendgrid, who changed their API with breaking changes, not really a Go problem
To repeat: "It seems that language-culturally, Go authors are fine with breaking changes".
For Go I’d say it’s the opposite and you have obviously been unlucky in your choices which you don’t want to talk about.
But it is not a universal experience. That is the only third party package with breaking changes I have experienced.
To repeat: "It seems that language-culturally, Go authors are fine with breaking changes". I just chose x as examples of near-stdlib, as opposed to appearing to complain about some library made by some random person with skill issues or who had a reasonable opinion that since almost nobody uses the library, it's OK to break compat. Protobuf is another. (not to mention the GCP libraries, that both break and move URLs, and/or get deprecated for a rewrite every Friday)
The standard library not breaking is table stakes for a language, so I find it hard to give credit to Go specifically for table stakes.
And it's not like Go standard library is not a bit messy. As any library would be in order to maintain compatibility. E.g. net.Dialer has Timeout (and Deadline), but it also has DialContext, introduced later.
If the Go standard library had managed to maintain table stakes compatibility without collecting cruft, that'd be more impressive. But as those are contradictory requirements in practice, we shouldn't expect that of any language.
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.
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.
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.
I did an analysis of Go dependencies[1] a few weeks ago and google/uuid is the 2nd most used dependency in the open source ecosystem, so its inclusion will be very impactful.
[1]: https://blog.thibaut-rousseau.com/blog/the-most-popular-go-d...
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.
Some chuckle head decided to replace the system with UUIDs. Now, they are no longer human memorable/readable/writable on paper/anything useful. Even better, they must have used some home grown implementation, because the codes were weirdly sequential. If you ever had to look at a dump of codes, the ids are almost identical minus a digit somewhere in the middle.
Destructive change that ruined a perfectly functional system.
It's funny how fast it is to just implement a counter and how much people rely on UUIDs to avoid it. If you already use postgres somewhere, just create a "counter" table for your namespace. You can easily count 10K-100k values per second or faster, with room to grow if you outscale that.
What do you get? The most efficient, compressible little integers you could ever want. You unlock data structures like roaring bitmaps/ treemaps. You cut memory to 25% depending on your cardinality (ie: you can use u16 or u32 in memory sometimes). You get insane compression benefits where you can get rows of these integers to take a few bits of data each after compression. You get faster hashmap lookups. It's just insane how this compounds into crazy downstream wins.
It is absolutely insane how little cost it is to do this and how many optimizations you unlock. But people somehow think that id generation will be their bottleneck, or maybe it's just easier to avoid a DB sometimes, or whatever, and so we see UUIDs everywhere. Although, agreed that most of the time you can just generate the unique id for data yourself.
In fairness, UUID is easier, but damn it wrecks performance.
BASKETBALL-9a176cbe-7655-4850-9e7f-b98c4b3b4704-FISH
CAKE-3a01d58f-59d3-4b0c-87dc-4152c816f442-POTATO
“Which row was it, ‘basketball fish’ or ‘cake potato’?
Of course, the words would need to be a checksum. As soon as you introduce them, nobody is looking at the hex again. Which is an improvement, since nobody is looking at all the hex now “it’s the one ending in ‘4ab’”.
But for exposed values (document ids, customer ids, that kind of thing), it can be awkward if a patient's id is suddenly "CRANKY-...-FART".
Note: FIPS181 was intended for passwords and I was using them as handy short human-readable record IDs as per your post. You probably shouldn't use FIPS181 for passwords in 2026 LOL.
Describing FIPS181 as pronounceable is optimistic. However its better than random text wrt human conversations. They start looking like mysterious assembly language mnemonics after awhile.
What are your favorite ways to approach this?
I think a maximal period linear feedback shift register might fit well.
Generally means it'll be going in unless something new comes up which alters people's thinking.
So, it makes sense for Go to introduce support for this as well.
https://github.com/stateless-me/uuidv47
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).
However, the net/http package is a different story. It indeed isn't very performant, though one should be careful to understand that that assessment is on relative terms; net/http still runs circles around some other languages' standard approaches to HTTP servers.
A big part of why net/http is relatively slow is also down to its goals and API surface. It's designed to be easy to use, not especially fast. By comparison, there's fasthttp [1], which lives up to its name, but is much harder to work with properly. The goal of chasing performance at all costs also leads to questionable design decisions, like fiber [2], based on fasthttp, which achieves some of its performance by violating Go's runtime guarantee that strings are immutable. That is a wild choice that the standard library authors would/could never make.
[1]: https://pkg.go.dev/github.com/valyala/fasthttp
[2]: https://pkg.go.dev/github.com/gofiber/fiber/v3
Something like http/v2 and net/v2. I know gnet had(has?) issues wit implementing tls because how the entire STD is designed to work. At the time, it was a great piece of software, but by now, it is slow and outdated. A lot of progress has been made since in networking, parsing, serialization, atomics and so on.
It's quite literally the opposite. The purpose of a stdlib is standardization, stability, and broad usefulness, not extreme performance. In fact, that can't be its purpose — you can only get max performance if you tune for your exact use case — but how could a stdlib that's by definition generic ever be able to do that?
> but then again there are faster libraries that can give you 3x performance(in case of numeric keys)
Yeah, exactly. If you can constrain your problem domain ("numeric keys only"), you can always squeeze out more performance than a generic algorithm can give you. Completely irrelevant as far as stdlib goes though.
> 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.
[0]: https://docs.python.org/3/library/urllib.request.html
[1]: https://github.com/trending/go?since=monthly
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.
[0]: https://docs.python.org/3/library/index.html
[1]: https://pkg.go.dev/std
Go's package management is actually one of its strongest points, so I think that it's unsurprising/good that some projects have lots of dependencies. But I still stand by the point that you shouldn't judge a language based on how many dependencies most programs written in it use.
(Except for JavaScript, where I have no problem judging it by the npm craziness :) )
https://news.ycombinator.com/newsguidelines.html
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.
The problems with a big "batteries included" standard library like go or python strives for, are that you will inevitably leave things out that at least some people consider "basic", like uuid, and parts of stdlib will probably have lower quality than third party libraries, like pythons urllib or gos log package, and it is constrained by needing to maintain backwards compatibility and being tied to the language's release cycle.
But I understand people have different opinions and that there will never be a standard library that appeases everyone. I don’t think “having a batteries included library” aims to appease everyone either. But mostly I just don’t understand the people who criticize Go for not having enough things in their standard library because Go’s standard library is one of the more useful (which may not be everyone’s ideal).
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
And then you answered about downstream code breakage totally outside the std lib.
I will be forever mad that they did not use that as a breaking opportunity to namespace the standard library. Something like: `import std.io` so that other libraries can never conflict.
Maybe it wasn't very good, but 2to3 was there from the start:
https://docs.python.org/3.0/library/2to3.html
The fact that we're discussing this at all is a reasonable argument for using a library function.
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.
I was disappointed by Go's poor support for human-focused logging. The log module is so basic that one might as well just use Printf. The slog module technically offers a line-based handler, but getting a traditional format out of it is painful at best, it lacks features that are common elsewhere, and it's somehow significantly slower than the json handler. I can only guess that it was added as an afterthought, by someone who doesn't normally do that kind of logging.
To be fair, I suppose this might make sense if Go is intended only for enterprisey environments. I often do projects outside of those environments, though, so I ended up spending a lot of time on a side quest to build what I expected to be built-in.
I haven't explored enough of the stdlib yet to know what else that I might expect is not there. If you have a wish list, would you care to share it?
I don’t disagree with you btw. JWT signing/verification and JWK support is especially something I would prefer had first class implementations. (I’m much less concerned with JWT parsing, which is trivial).
You can't comment like this on Hacker News, no matter what you're replying to. If you wouldn't mind reviewing https://news.ycombinator.com/newsguidelines.html and taking the intended spirit of the site more to heart, we'd be grateful.
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).
I've never seen a go program that is more than hello world that has only 1 or 2 dependencies in my whole professional life.
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...
However I would still advocate for it over C in scenarios easily covered by TinyGo and TamaGo.
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
The maintainers did the right thing by just saying "no."
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.
You can use different encodings based on context, just like with a random blob of bytes.
One example where UUIDs are useful is usage as primary keys in databases. The constraints provide benefits, such as global uniqueness across distributed systems.
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
I don't think it's a strong hiring signal if they weren't already familiar with APIs for (de)serialization in between, because if they're worth anything then they'll just pick that up from documentation and be done with it.
For one position? To fill a department or company?
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.
Go’s core design philosophy is stability. This means backwards compatibility forever. But really, even more than that. The community is largely against “v2” libraries. After the first version is introduced, Go devs trend towards stability, live with its flaws, and are super hesitant to fix things with a “v2”.
There have been exceptions. After 20 years of the frankly horrible json library, a v2 one is in the works.
Most of the uuid concerns come from a place of concern. After the api is added to the standard library, it will be the canonical api forever.
There are surely pros and cons to this design philosophy. I just don’t understand why people who disagree with Go’s core goals don’t just use a different language? Sorry to take a jab here, but are we really short on programming languages that introduce the wrong v1 api, so then the language ends up with codebases that depend on v1, v2, and v3? (Looking at you Java, Python, and C#)
But regardless of API ergonomics, I would love to have UUID v4 and v7 in the stdlib.