Live data from Hacker News

Go subtleties

harrisoncramer.me

171–180 of 190 posts

Re: Go subtleties

#171
post #165
post #91

my favorite go trick is a simple semaphore using make(chan struct{}, CONCURRENCY) to throttle REST api calls and other concurrent goroutines. It’s really elegant acquisition by reading, and releasing the semaphore by writing. Great to limit your rest / http crawlers to 8 concurrent calls like a web browser.

Why not use the standard-library adjacent semaphore package? One problem with using a channel as a semaphore is you need to track if you've closed the channel when "releasing". https://pkg.go.dev/golang.org/x/sync/semaphore#Weighted.Acqu...

> is you need to track if you've closed the channel

There is where you can use a function that captures the channel and guarantees that no matter how many times it is called that it only closes the channel once.

Re: Go subtleties

#172

Earlier quoted context omitted.

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.

Totally agree.

Re: Go subtleties

#173
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.

My bad, I just double-checked and Go did the dumb thing again: They are indeed representing full code points rather than scalars like everyone else.

Re: Go subtleties

#174
post #115

I balked a little when the article refers to format strings as "string interpolation" but there's multiple comments here running with it. Am I out of date and we just call that string interpolation these days? I also found this very confusing: > When updating a map inside of a loop there’s no guarantee that the update will be made during that iteration. The only guarantee is that by the time the loop finishes, the ma…

"Am I out of date and we just call that string interpolation these days?" It's all just spelling. Your compiler just turns x = "I want ${number/12|round} dozen eggs, ${name|namecase}" into x = StrCon("I want ", round(number/12), " dozen eggs, ", namecase(name)) anyhow. It's not a huge transform. I think people get bizarrely hung up on the tiny details of this between languages... but then, I think that extensive use…

> It's not a huge transform.

To write? Maybe so. Now try to modify it. Enjoy matching quotation marks and juggling commas. It's awful, which is why everybody uses fmt.Sprintf() instead.

String interpolation is a must have these days, I wish the Go devs would wise up to that fact.

Re: Go subtleties

#175

Earlier quoted context omitted.

In Go, string effectively serves as a read-only slice, if we are talking about bytes. ReadOnlySpan in C# is great! In my opinion, Go essentially designed in “span” from the start.

Yeah I think the C# team was definitely influenced by Go with their addition of Spans.. Interesting approach regarding using strings as containers for raw bytes, but when you create one over a []byte I believe it makes a copy almost always (always?) so you can’t get a zero-cost read-only view of the data to pass to other functions.

Like everything else in Go, spans predate it for a few decades.

Re: Go subtleties

#176

Great list! Reminds me to check out more of the new stuff in 1.25. The one thing I wish Go had more than anything is read-only slices (like C#). The one thing I wish more other languages had that Go has is structural typing (anything with Foo() method can be used as an interface { Foo() }.

In Go, string effectively serves as a read-only slice, if we are talking about bytes. ReadOnlySpan in C# is great! In my opinion, Go essentially designed in “span” from the start.

System languages from 1980's already had the span concept.

One way that you will find it is that they used to be called open arrays in some of them.

Re: Go subtleties

#177
post #102

The wording "Subtleties" used here is some weird/improper. I see nothing subtle here. They are all basic knowledge a qualified Go programmer should know about. They are many real subtleties in Go, which even many professional Go programmers are not aware of. Here are some of them: https://go101.org/blog/2025-10-22-some-real-go-subtleties.ht...

The examples in your link don’t seem to be very useful compared to the subject of this post. “for true {...} and for {...} are not eqivalent” So what? The compiler will tell you the first time you try to run that “for true” abomination that it is invalid code.

Subtleties are not necessary to be very useful. They, are just real subtleties. :)

> > “for true {...} and for {...} are not eqivalent”

> So what? The compiler will tell you the first time you try to run that “for true” abomination that it is invalid code.

It teaches you know that, when you write

    func bar() int {
         for true {
              ...
         }
         return 0 // whatever
    }
You can write it as

    func bar() int {
         for {
              ...
         }
    }
The compiler will not teach you this. ;D

Usefulness might be subjective. Personally, the last two subtleties mentioned in the article are useful for me too.

You may find some useful (in your opinion) subtleties in the Go Details and Tips 101 book: https://go101.org/details-and-tips/101.html, and some since-Go-1.22/3 ones here: https://go101.org/blog/2024-03-01-for-loop-semantic-changes-... and https://go101.org/blog/2025-03-15-some-facts-about-iterators...

Re: Go subtleties

#178

Earlier quoted context omitted.

> 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.

My bad, I just double-checked and Go did the dumb thing again: They are indeed representing full code points rather than scalars like everyone else.

Thank you for striving to be correct and taking the time for the investigation.

Re: Go subtleties

#179
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

Seeing as two of the authors designed utf8 (or at least concurrent to others), I think it’s safe to defer to their expertise and nomenclature here.

http://enwp.org/Appeal_to_accomplishment

Your use of the fallacy falls short of the reasoning standard expected here on HN. I did not downvote you, because I'd rather engage with words and effect change, but it does not surprise me that someone else did.

Re: Go subtleties

#180
post #167

Earlier quoted context omitted.

I can't think of good way to give programmers control over boxing without adding a bunch of complexity that nobody wants.. but it doesn't seem out of the realm of possibility that the linter could detect issues like this. It should be able to spot methods that aren't nil-safe and spot nil values of those types ending up in interfaces with those methods. Then you'd have less explaining to do!

It's a bit difficult statically because it is a flow sensitive analysis. You are not wrong that it is a sharp edge. Completely removing nils from interfaces is not possible because: 1. not backward compatible However I would nuance a little. Having an empty interface ie. a untyped nil is useful. Having typed nils in interfaces is arguable. Because every value type that has methods can make pointer. That means potenti…

"empty interface" meaning an interface value that is empty i.e. nil interface... ofc
Post reply on HN