| ▲ | richbell a day ago |
| I wish the discourse that Go is a "simple" language would die. Despite its veneer, once you start writing Go it quickly becomes apparent that it isn't simple. Hidden complexity and footguns are abundant (e.g., https://archive.ph/WcyF4). It's nevertheless a useful language, and I use it quite a bit, but it's not "simple". |
|
| ▲ | jonathanstrange a day ago | parent | next [-] |
| I have no idea why anyone would say it's not simple, it's super-simple. Learning how duck typing works with interfaces and how to use it is perhaps the only hurdle. In my experience, only certain BASIC dialects like VisualBasic are simpler. |
| |
| ▲ | LinXitoW a day ago | parent [-] | | I think the sticking point is what people mean when they say simple. To me, and likely to many saying Go isn't simple, simple is not a synonym for easy. Go is easy, but it is not simple. For example, solving the problem of generics in a generic way from the start so the same problem can be addressed in the same way everywhere, would be simple, but maybe not (as) easy. Contrast that to giving the runtime/standard library a special exception with maps and lists. That's easy, but not simple. People used to literally use code generators or weird UTF-8 characters to fake generics, that's not remotely simple. | | |
| ▲ | stouset a day ago | parent [-] | | Frankly code generators to fake generics aren’t remotely easy either. |
|
|
|
| ▲ | nulld3v a day ago | parent | prev | next [-] |
| This 100%, I was just about to type a long rant up about this. There are so many weird parts of the language that took me forever to grasp, and in many cases, I still don't have an intuitive grasp of things. And plenty of other examples that aren't in that article: - You have a struct with an embedded interface. Does the outer struct satisfy the embedded interface? And can I type assert the outer struct into whatever embedded struct is fulfilling the inner interface? - When should I pass by value and when should I pass by reference? Like I generally know when to choose which, but do I really know without performing a benchmark? And what about arrays? Should I store pointers in them? But it also seems that people just don't care and just randomly roll the dice on when to return a pointer or a value? - Shorthand variable declaration. How does it work when you shorthand declare two variables but one of them already exists? Don't both answering the questions, that's not the problem. The problem is that it's just not intuitive enough such that I'm confident I know the correct answer. |
| |
| ▲ | B-Con 19 hours ago | parent | next [-] | | The first is simply a question about what an embedded interface is. Any way in which you learned about this feature should also answer the question. The second isn't related to Go. The third I can see as being a bit confusing, but isn't it something you try once and then remember forever? Here's one: Creating a new variable via shorthand that shadows a variable in an outer scope - that can be confusing and an easy mistake to make. But broadly, I would strongly advocate that it is simpler than most other languages, even if it has some quirks. In the same vein of "If I had more time, I'd write a shorter letter", sometimes it takes a bit of time to understand why something is simpler than the alternatives. No language has zero ramp-up. Go doesn't exist in a vacuum, you have to compare it's learning curve and complexity to other languages. | |
| ▲ | dondraper36 a day ago | parent | prev | next [-] | | I am not going to answer the questions, but this is a very strange complaint, to be honest. For example, passing by value/passing by reference is something covered immediately in the Go FAQ document once and for all. Everything is passed by value in Go, that is it. There should be no confusion at all. If you spend 15 minutes reading Russ Cox's post on the internals of the most common data types, you will also understand what data structures have implicit pointers under the hood. | | |
| ▲ | nulld3v a day ago | parent [-] | | Well yes obviously I know everything is passed by value, just like in literally every other popular language. I'm talking about the difference between pointer parameters/receivers vs value parameters/receivers. |
| |
| ▲ | KingOfCoders a day ago | parent | prev | next [-] | | Your thinking is too complex for Go. You might be better of with Rust. Same about benchmarking, if you want and need the fastest code, or the best memory management, use Rust. If you need something faster than Python in general but not the fastest, use Go. | | |
| ▲ | nulld3v a day ago | parent [-] | | But that's the thing right? Like I come from Java. In Java, we have objects. They are pointers. That's it. You don't get to decide on whether you want a pointer or a value (I guess primitives are an exception lol). But it was so simple! And same in JavaScript. Everything is a pointer except primitives. That's it. End of story. And I have written Rust too, and while the situation is definitely more complicated there, the guidance is extremely simple and straightforward: If the struct implements Copy, then it is very cheap to copy and you should pass by value. Otherwise, you should pass by pointer/reference. And meanwhile in Go, I just see pointers and values being used seemingly interchangeably, and seemingly at random. |
| |
| ▲ | ralegh a day ago | parent | prev [-] | | > but do I really know without performing a benchmark? Not really. But that’s one of Rob Pikes rules [1], I think the intention is to write whatever is simplest and optimize later. The programmer doesn’t need to remember 100 rules about how memory is allocated in different situations. [1] https://users.ece.utexas.edu/~adnan/pike.html | | |
| ▲ | nulld3v a day ago | parent [-] | | I mean it's a great idea, and I fully agree that I do not want to worry about memory allocation. So then why is `make` a thing? And why is `new` a thing? And why can't I take an address to a primitive/literal? And yet I can still take an address to a struct initialization? And why can't I take an address to anything that's returned by a function? | | |
|
|
|
| ▲ | LandR a day ago | parent | prev | next [-] |
| It's easy not simple, but the consequence is that any complexity that other languages handles for you, in go gets forced onto the developer. There's more stuff to think about, because the language is doing less for you. |
|
| ▲ | KingOfCoders a day ago | parent | prev [-] |
| Yes, like "Opening Brace Can't Be Placed on a Separate Line" (from your link). Everyone can read Go code and understand what happens. There are some minor difficulties like func (*A) vs func (A)., |
| |
| ▲ | eru a day ago | parent [-] | | RiscV assembly is even easier to read by that metric. | | |
| ▲ | KingOfCoders a day ago | parent [-] | | My assembler days were 4 decades ago, but "Everyone can read Go code and understand what happens." There seems to be a difference between "easy to read" and "understand what happens" - or what happens on what level. The challenge is that there is a tradeoff between the two. Assembler is too low to understand what "really" happens, on the other hand Haskell for example with Monad stacks is again very easy to read + understand what happens "most of the time", but hard to understand all the abstracted away side effects. In Haskell with add 3 5
everything can happen beside what you see.In assembler ld a, 3
add a, 5
nothing happens except these two instructions.The tradeoff is how much you want to be explicit, with the downside of creating too much noise, and how much you want to abstract away, with the downside of magic happening somewhere. | | |
| ▲ | eru a day ago | parent [-] | | Yes. And to be less snarky: Go doesn't really sit on the efficiency frontier here: It requires you to write a lot of stuff by hand and is incredibly verbose, but it also does a lot of magic behind the scenes. |
|
|
|