Live data from Hacker News

Go subtleties

harrisoncramer.me

151–160 of 190 posts

Re: Go subtleties

#151
post #126

Earlier quoted context omitted.

Oh boi, all my RW mutexes for maps across goroutines would disagree.

Use sync.Map or create simple wrapper to control access.

… the documentation for sync.Map literally says:

> The Map type is specialized. Most code should use a plain Go map instead, with separate locking or coordination, for better type safety and to make it easier to maintain other invariants along with the map content.

The documentation basically says that it's optimized for some cases that wouldn't affect the complaint above.

Re: Go subtleties

#152
post #140

Earlier quoted context omitted.

I like to say this: "Only my code is allowed to be clever" But, on a serious note, I agree with you. Go lacks a lot of power, especially in its type system, that causes a ton of problems (and downtime) that in other languages is trivial to prevent statically.

Formal proof languages are pretty neat, but nobody really uses them in the real world. Among the languages that people actually use on a normal basis, even those that claim to have extensive type systems, they still rely on testing for most everything, and once you're relying on testing anyway the type system isn't any kind of real saviour. There is, perhaps, some segment of the developer community who believe that t…

Typescript’s type system is a huge leap up from JavaScript.

You still need tests for functionality (this function does what it should) but the type system removes many error cases automatically.

Re: Go subtleties

#153
post #151
post #126

Earlier quoted context omitted.

Use sync.Map or create simple wrapper to control access.

… the documentation for sync.Map literally says: > The Map type is specialized. Most code should use a plain Go map instead, with separate locking or coordination, for better type safety and to make it easier to maintain other invariants along with the map content. The documentation basically says that it's optimized for some cases that wouldn't affect the complaint above.

If you want to be pedantic, you can use https://github.com/puzpuzpuz/xsync which has generics and is faster than native sync.Map

Re: Go subtleties

#154

There is mention of how len() is bytes, not “characters”. A further subtlety: a rune (codepoint) is still not necessarily a “character” in terms of what is displayed for users — that would be a “grapheme”. A grapheme can be multiple codepoints, with modifiers, joiners, etc. This is true in all languages, it’s a Unicode thing, not a Go thing. Shameless plug, here is a grapheme tokenizer for Go: https://github.com/clip…

Here’s my favorite post on the subject https://adam-p.ca/blog/2025/04/string-length/

Finally an article that doesn't pretend grapheme clusters are the be-all end-all of Unicode handling.

I'm saving this one. Not exactly how I'd explain it, but it's simplified enough to share with my current co-workers without being misleading.

Re: Go subtleties

#155
post #122

Earlier quoted context omitted.

out of curiosity (not meant snidely), do you have an example of a case where the weaker type system resulted in serious problems?

Pretty much any null pointer deference error ever? But it is hardly ever the weak type system that is at fault, just good use of a stronger type system could have prevented the issue. Once you start to make "invalid states unpresentable" and enforcing those states at the edges of your type system suddenly a lot of bizarre errors don't happen anymore.

NPEs are also present in a lot of languages with "stronger" type systems though. Is there a specific language you're comparing against?

Re: Go subtleties

#156
post #93

FTA: “In Go, empty structs occupy zero bytes. The Go runtime handles all zero-sized allocations, including empty structs, by returning a single, special memory address that takes up no space. This is why they’re commonly used to signal on channels when you don’t actually have to send any data. Compare this to booleans, which still must occupy some space.” I would expect the compiler to ensure that all references to t…

[deleted]

Re: Go subtleties

#157
My opinion after using go professionally for ~2 years and repeatedly running into gotchas such as https://go.dev/blog/loopvar-preview is that it's just not a good language.

A lot of people praise it for it's "simplicity" and "explicitness" but frankly, even just figuring out whether something is being passed by reference or value is often complicated. If you're writing code where you never care about that, sure. But for any real project it's not actually better or simpler than C++ or Python.

Re: Go subtleties

#158
post #84

FTA: > Runes correspond to code points in Go, which are between 1 and 4 bytes long. That's the dumbest thing I've read in this month. Why did they use the wrong word, sowing confusion¹, when any other programming language and the Unicode standard uses the correct expression "code point"? ¹ https://codepoints.net/runic already exists

> uses the correct expression "code point"

Actually no, these are Unicode scalars, not code points; they exclude the surrogate category.

I agree that rune is a very poor name for it. It both mistakes what runes actually are and clashes with the runic block. But C# has adopted the Rune name for some reason.

Rust simply calls these char, and OCaml uchar (unicode char), which are much better choices.

Re: Go subtleties

#159

There is mention of how len() is bytes, not “characters”. A further subtlety: a rune (codepoint) is still not necessarily a “character” in terms of what is displayed for users — that would be a “grapheme”. A grapheme can be multiple codepoints, with modifiers, joiners, etc. This is true in all languages, it’s a Unicode thing, not a Go thing. Shameless plug, here is a grapheme tokenizer for Go: https://github.com/clip…

len() is also returning int instead of uint/uint64 in Go.

I do not use Go but ran into this when I had to write a Go wrapper for some Rust stuff the other day. I was baffled.

Re: Go subtleties

#160

Earlier quoted context omitted.

How much is premature in time? 10 years? 20, 30 years?

So for me, the question is: are these two things intrinsically the same or coincidentally the same? If it is intrinsically the same, then an abstraction/centralization of logic is correct. If they are coincidentally the same, then its better to keep them separate. Its premature if I don't know the answer to that question with my current information, which is a common scenario for me when I'm initially writing a new s…

On the other hand, when your abstraction has more configuration options than methods, it is a sign that (years ago) it really wasn't an abstract at all.
Post reply on HN