It seems he's not happy anymore with the new direction of Go because they're implementing things from other languages.
woadwarrior01 3 hours ago [-]
> noCopy is a special marker for types that must not be copied after their first use.
if it looks like a hack, walks like a hack, and quacks like a hack...
stevecoalbear 2 hours ago [-]
Go's full of hacks, and holds no shame over it. Zero-initialized everything, and proceeding to 'defer' instead of RAII, generic builtin types despite lack of generics (until recently), no builtin list type, slices having capacity...
This was Go's design philosophy until Rob Pike left - to do the simple thing simply and not try to be clever about it.
tialaramex 1 hours ago [-]
> no builtin list type
Wait, which thing do you mean by a "list type" ? A growable array type like Rust's Vec<T> or C++ std::vector<T> or the ArrayList type seen in several languages ?
Or do you mean a linked list type akin to C++ std::list or std::forward_list or Rust's std::collections::LinkedList ?
"List" is vague, which is appropriate if you're talking about very high level abstractions where it doesn't matter how it works and 5 gigabytes, 5 bits, 5 weeks or 5 seconds are all finite so who cares - but in the real world we usually do care.
josephg 56 minutes ago [-]
It’s not simple though. The language is simpler, sure. But you pay for language simplicity with program complexity. In go, you have to write and debug a lot more code.
I don’t mind spending a few extra weeks learning a more complex language if doing so saves me months of time down the track programming and debugging. That is an excellent investment.
mainde 38 minutes ago [-]
I've not seen this in my experience tbh, the extra code that Go requires is ugly but not complex, the lack of ergonomics actively discourages "clever" solutions and, as a result of this, people tend to write the kind of straightforward code that doesn't end up needing lengthy programming or intense debugging.
At my workplace we've used many languages over the years (C#, Python, Go) and Go teams are the ones that by far do the least amount of yak shaving and have the most intelligible codebases.
kbolino 36 minutes ago [-]
RAII has the advantage that you can't forget to do it, but defer has the advantage that you can handle failure in ways other than panicking. Of course, in many cases (e.g. closing a file), there's generally not much you can do anyway even if you want to handle the error directly, but at least it's possible.
bewareofscams 12 minutes ago [-]
Rust can handle that with RAII without panicking just fine. And not only Rust..
bewareofscams 13 minutes ago [-]
More like Pike's design philosophy was "let's do some half-thought things and sabotage any current or future improvement proposal for decades to come, while gaslighting everyone that Go is good because Google and because people can't see difference between 'systems' and 'system' programming".
breakingcups 2 hours ago [-]
I'd want to blame Go's compatibility guarantee for this, but I can't because it wouldn't actually stop them from adding a proper solution for this..
Just like the magic comments, it's a sad thing to see appear in this language because it feels like magic incantations one has to know that bend over backwards to not actually extend the language to fit the use case.
programcookie 1 hours ago [-]
This shipped with Go 1.7, almost ten years ago to the day.
pjmlp 1 hours ago [-]
The whole Go design philosophy in one sentence, that is what one gets by refusing to adopt modern language practices.
43 minutes ago [-]
never_inline 2 hours ago [-]
Every language can't be rust.
neilalexander 3 hours ago [-]
It's not really a hack. It's a hint to a static analyser, that's all.
tgv 2 hours ago [-]
Nah... I like Go, but this is a hack. Wiktionary --not the ultimate authority, I know, but still-- defines to hack as: To make a quick code change to patch a computer program, often one that, while being effective, is inelegant or makes the program harder to maintain.
I could accept having an anonymous embedding as a kind of syntax directive. So many languages have had directives bolted on later, so that wouldn't be a deal breaker. But then it should be accessible in all code and (external) code should be able to implement behavior as well.
woadwarrior01 2 hours ago [-]
Most languages would encode such behavior in a trait or a protocol instead of a zero-length struct field. It's type information and ought to be encoded in the type. From that perspective, I think it is a hack.
kbolino 2 hours ago [-]
This feels like a style complaint and not one about substance. An inaccessible (because it's named _) zero-length struct field is just another kind of metadata. It also doesn't require you to pollute the method set, which would be a bigger issue.
The real hack to me is that anything which simply has Lock() and Unlock() methods is considered uncopyable.
reorder9695 2 hours ago [-]
Coming from Rust anyway (can't say I'm familiar with Go), nothing about having it as a trait would pollute the method set, traits don't have to have methods (e.g. pin, unpin, send, sync, etc.). Yes a zero length field can be metadata and this is a style complaint but a struct's fields are traditionally its data and the type is its metadata, I feel like it's harmful to mix these two as I at least wouldn't generally look at fields to find metadata for the struct.
kbolino 2 hours ago [-]
Interfaces in Go (the closest equivalent to traits in Rust) don't have to have methods either, but they are structurally typed. This is like "static duck typing" if you will. So an interface with no methods is implemented by every type in the language (indeed, this became such a useful pattern that the name "any" was reserved for it in Go 1.18).
Marker interfaces can exist in Go, but here they are another kind of hack. They must define at least one method (which doesn't have to be public), though that method is never actually meant to be called.
woadwarrior01 2 hours ago [-]
I'm only peripherally familiar with Go. IIRC, Rust defaults to move-only structs with the option to make them copyable with the Copy trait. Swift defaults to copyable structs (like Go), but has a ~Copyable generic type constraint to make them move-only.
stevecoalbear 2 hours ago [-]
Go's entire schtick is being simple, eschewing language complexity in favour of letting the programmer handle it themself. Like C, but with pointer safety and garbage collection.
We learned from C++ and Rust that languages can be so smart that people can't effectively use them. Go is the opposite. It's so dumb that anyone can use it, but it doesn't have some native language features you might want.
insanitybit 2 hours ago [-]
How is this simple? It's basically a hint to `go vet` that uses a special interface pattern. I'm baffled by what some people call "simple" lol
11 minutes ago [-]
CamouflagedKiwi 2 hours ago [-]
This feels like it should ideally be something public in the structs package so anyone can leverage it, not just a specially blessed internal thing for the sync package.
I agree, its a nice piece of semantics to be added to a struct
wbl 1 hours ago [-]
You can very easily define one yourself.
kbolino 58 minutes ago [-]
You can exploit the mechanism described in the article yourself, but it's already changed once in the past and is not part of any compatibility guarantee. As with structs.HostLayout, a blessed structs.NoCopy in the standard library could guarantee that it works forever. I think the bigger issue remains that it doesn't actually do anything in the language (but, then again, neither does structs.HostLayout--yet).
- https://x.com/valyala/status/2088638160242683954
He also gave an answer of what he would change now: https://itnext.io/go-evolves-in-the-wrong-direction-7dfda8a1...
It seems he's not happy anymore with the new direction of Go because they're implementing things from other languages.
if it looks like a hack, walks like a hack, and quacks like a hack...
This was Go's design philosophy until Rob Pike left - to do the simple thing simply and not try to be clever about it.
Wait, which thing do you mean by a "list type" ? A growable array type like Rust's Vec<T> or C++ std::vector<T> or the ArrayList type seen in several languages ?
Or do you mean a linked list type akin to C++ std::list or std::forward_list or Rust's std::collections::LinkedList ?
"List" is vague, which is appropriate if you're talking about very high level abstractions where it doesn't matter how it works and 5 gigabytes, 5 bits, 5 weeks or 5 seconds are all finite so who cares - but in the real world we usually do care.
I don’t mind spending a few extra weeks learning a more complex language if doing so saves me months of time down the track programming and debugging. That is an excellent investment.
At my workplace we've used many languages over the years (C#, Python, Go) and Go teams are the ones that by far do the least amount of yak shaving and have the most intelligible codebases.
Just like the magic comments, it's a sad thing to see appear in this language because it feels like magic incantations one has to know that bend over backwards to not actually extend the language to fit the use case.
I could accept having an anonymous embedding as a kind of syntax directive. So many languages have had directives bolted on later, so that wouldn't be a deal breaker. But then it should be accessible in all code and (external) code should be able to implement behavior as well.
The real hack to me is that anything which simply has Lock() and Unlock() methods is considered uncopyable.
Marker interfaces can exist in Go, but here they are another kind of hack. They must define at least one method (which doesn't have to be public), though that method is never actually meant to be called.
We learned from C++ and Rust that languages can be so smart that people can't effectively use them. Go is the opposite. It's so dumb that anyone can use it, but it doesn't have some native language features you might want.