[HN Gopher] Go 1.18 Beta 1 is available, with generics
       ___________________________________________________________________
        
       Go 1.18 Beta 1 is available, with generics
        
       Author : pcw888
       Score  : 196 points
       Date   : 2021-12-15 10:30 UTC (12 hours ago)
        
 (HTM) web link (go.dev)
 (TXT) w3m dump (go.dev)
        
       | yannoninator wrote:
       | A better xmas present than anything I've ever received. bravo!
        
       | zerr wrote:
       | I hope the next big thing is a proper error handling instead of
       | if-hell.
        
         | Cthulhu_ wrote:
         | There was a spurt of this before they seriously went to work on
         | generics, and the conclusion was "actually, it's fine the way
         | it is". There's huge discussions on the matter as well as
         | various proposals, but they all came with caveats that, in the
         | end, weren't considered a significant improvement.
         | 
         | That said, with generics, it should be possible to change to
         | the 'Either' style [0] of error handling. And with another
         | compiler feature to be added, er, 'exhaustive switch/case' or
         | whatever you want to call it, they can make it a compiler error
         | to not handle the error case. That said, I don't see the
         | language developers or community making it a standard anytime
         | soon.
         | 
         | The current style of error handling doesn't hurt enough. It's
         | verbose and repetitive, sure, but if the alternative is
         | something clever or magic, it's not the way to go.
         | 
         | [0] https://www.scala-
         | lang.org/api/2.13.6/scala/util/Either.html
        
         | 5e92cb50239222b wrote:
         | Give it 20 more years of evolution (considering we're talking
         | about Go, probably 70 years), and we get another C++. A Google
         | of the future (let's call it Scroogle) starts another language
         | that can be used by recent graduates that have no idea about
         | what they're doing to write mountains of JSON fiddling
         | boilerplate. Rinse and repeat.
        
           | nauticacom wrote:
           | Hey, don't be so pessimistic. We'll probably have another
           | serialization protocol by then.
        
         | ernst_klim wrote:
         | I think people are constantly focusing on the wrong target here
         | though.
         | 
         | The main problem of error handling in Go is not the tediousness
         | of writing                   if err != nil {}
         | 
         | after each function (it's not nice but bearable).
         | 
         | The main problem is how hard to actually process errors.
         | 
         | In Go, there are three types of errors: custom structs with
         | contextual info, predefined error constants of type stringError
         | aka sentinels, and wrapped stringErrors, produced in-place by
         | fmt.Errorf.
         | 
         | The first ones can be matched by type coersion or errors.As
         | function. The second ones can be compared with == operator. The
         | last ones can be either parsed by regex, or matched by the
         | error they wrap and then unwrapped.
         | 
         | Oh, and the signature is nearly always just error, so basically
         | to process errors gracefully you have to read the docs for each
         | function instead of just looking at the signature.
         | 
         | It's so extremely inconvenient and tedious so nearly nobody
         | process errors in Go, despite what language creators say.
         | People either return error to the top of the callstack, maybe
         | wrapping it in additional string, thus emulating poor man's
         | exceptions without stack traces, or panic in-place. Nearly
         | nobody catches and matches errors, as many in C++, Java, Scala
         | or OCaml|Haskell world do.
        
         | lowmagnet wrote:
         | This is the biggest complaint after generics, and there are a
         | few proposals to dynamically resolve it in either libraries or
         | language features. These proposals are in the go2drafts
         | section, but keep in mind that this is where generics were
         | originally placed on the timeline. Yet here we are with a
         | backward-compatible change to the language in the sub-2.0
         | version of the language.
        
       | laerus wrote:
       | > The key point here is our programmers are Googlers, they're not
       | researchers. They're typically, fairly young, fresh out of
       | school, probably learned Java, maybe learned C or C++, probably
       | learned Python. They're not capable of understanding a brilliant
       | language but we want to use them to build good software. So, the
       | language that we give them has to be easy for them to understand
       | and easy to adopt.
        
       | honkycat wrote:
       | I'm going to start writing functional Golang and none of you can
       | stop me
        
       | neillyons wrote:
       | Cool. Does anyone know of libraries that are using Go generics
       | yet?
        
       | quantum_state wrote:
       | Nice!
        
       | mfrw wrote:
       | A quick[0] 13min video on generics by Ian Lance Taylor.
       | 
       | [0]: https://www.youtube.com/watch?v=nr8EpUO9jhw
        
         | e12e wrote:
         | Thank you. I'm not a gopher - but shouldn't code-gen be
         | mentioned as an alternative too? Or is that used for something
         | else?
        
       | dragandj wrote:
       | So now it turns out that generics are good?
        
         | mfrw wrote:
         | It remains to bee seen, meanwhile Rob Pike did comment[0], we
         | should refrain from changing libraries in 1.18 immediately
         | after generics are in.
         | 
         | "The reason is simple and compelling: It's too much to do all
         | at once, and we might get it wrong."
         | 
         | [0]: https://github.com/golang/go/issues/48918
        
           | Cthulhu_ wrote:
           | > It's too much to do all at once, and we might get it wrong.
           | 
           | If only people realized this about most software projects.
           | There's a lot of hubris and under-estimation in software
           | engineering.
        
         | rob74 wrote:
         | The Go team's stance on generics has never been "generics =
         | bad", but "generics have advantages and disadvantages, and if
         | we find an implementation which finds a good compromise between
         | the advantages and disadvantages, we will do it". Which they
         | now did. Let's hope it really turns out to be a good
         | compromise...
        
           | zerr wrote:
           | It was due to the arrogance and incompetence of a couple of
           | ex-AT&T authorities in the team.
        
             | hu3 wrote:
             | Is there a source for that?
             | 
             | I ask because instances I read from the team were in the
             | direction of: "We will gather enough use cases to decide on
             | the matter".
        
               | gadflyinyoureye wrote:
               | While the GP was a bit...harsh, the main reason people
               | have that view is generics, as a problem space, were
               | solved. Java's way was published years ago. As was
               | .NET's. Other languages exist which have some form
               | generics. The argument of "gather enough use cases to
               | decide on the matter" feels like a punt given the use
               | cases already exist and were known in the industry for
               | the past 30 years.
        
               | hu3 wrote:
               | Perhaps. But in hindsight, Go's generics implementation
               | turned different enough to warrant benefit of the doubt
               | in my opinion. A notable difference is that Go interfaces
               | are implicit while C# and Java are explicit and that
               | affects Go generics.
        
               | rob74 wrote:
               | The problem space may seem solved, but apparently it's
               | still not as easy as it looks from the outside. You don't
               | have to take my word for it, Cthulhu_ linked a comment by
               | Russ Cox (a major contributor to Go) from a few years ago
               | above: https://news.ycombinator.com/item?id=9622417
               | 
               | > _We have spoken to a few true experts in Java generics
               | and each of them has said roughly the same thing: be very
               | careful, it 's not as easy as it looks, and you're stuck
               | with all the mistakes you make._
        
               | gadflyinyoureye wrote:
               | I agree. From my Java experience most people don't do a
               | lot with them. List<Something> and the like. It makes
               | things like boiler plate easier.
               | 
               | I'm not saying it's easy to implement. Rather the ideas
               | are there and implementable. Typescript has them and it's
               | relatively young.
        
             | lowmagnet wrote:
             | It was due to the careful and deliberate nature of the Go
             | team, and the backward compatibility guarantee. It took
             | years for the group to put together a proposal with minimal
             | changes to the runtime and core libraries, and this
             | implementation in 1.18 will be limited in scope to only add
             | the feature, waiting for future versions to update other
             | core libraries to adapt generics in a backward-compatible
             | way.
        
             | Cthulhu_ wrote:
             | Have you even looked at other languages' implementation of
             | generics? Java's implementation takes up a significant part
             | of the language spec, compiler, and VM for example.
             | 
             | Here's an insightful comment from some time ago, explaining
             | why it's a technical issue, not a political one:
             | https://news.ycombinator.com/item?id=9622417 It links to
             | this FAQ highlighting a LOT of the complexities and
             | pitfalls of generics in Java, things that are all to easily
             | overlooked by armchair language expert: http://www.angelika
             | langer.com/GenericsFAQ/FAQSections/TypePa.... Note that
             | that's just one chapter in a very large document.
             | 
             | Comments like this say more about their author's arrogance
             | than that of the Go language team.
        
               | nauticacom wrote:
               | To me, "takes up a significant part of the language spec,
               | compiler, and VM" isn't a meaningful reason to exclude
               | something from a language, unless it's a hobby project.
               | The job of languages, imo, is to provide
               | tools/features/syntax for expressing problems, whether
               | their implementation is complex or not. Ruby is an
               | incredible language to use, but its implementation is
               | notoriously hairy. That internal complexity is not
               | something that matters to me in the slightest.
               | 
               | I understand the Go team's reluctance to get the _user-
               | facing_ interface wrong, and end up with something like
               | type-erasure in Java; that 's slightly connected with
               | implementation complexity, but saying "it's complex to
               | implement and specify" doesn't seem enough to me.
               | 
               | [edit: made it clearer that this is my thought on the job
               | of languages and not some universal truth]
        
               | remus wrote:
               | > It should be noted that "takes up a significant part of
               | the language spec, compiler, and VM" isn't a meaningful
               | reason to exclude something from a language, unless it's
               | a hobby project.
               | 
               | If we assume complexity ~= "takes up a significant part
               | of the language spec, compiler, and VM" then I think it's
               | an excellent reason not to include something! Somebody
               | has to maintain this stuff and making it complicated
               | makes that hard, which in turn means less time to spend
               | on things like tooling, performance improvements and
               | documentation which then makes our lives as users of the
               | language harder.
               | 
               | Of course there is a trade-off here but I think, in
               | general, the go team manage to strike a nice balance.
        
               | nauticacom wrote:
               | Right, but the entire point of my comment was that "takes
               | up a significant part of the language spec, compiler, and
               | VM" is _not_ a good approximation of complexity. It can
               | be related, but it is not necessarily true that something
               | with a complex implementation has a complex interface.
        
               | remus wrote:
               | I think we are talking past each other a bit, as I
               | completely agree with
               | 
               | > it is not necessarily true that something with a
               | complex implementation has a complex interface.
               | 
               | In turn, my point is that as a language implementer you
               | only have so much time available to work on the language
               | and surrounding ecosystem. If your time is spent dealing
               | with a complex spec, compiler and VM then you have less
               | time to spend on the rest of the ecosystem. I think go
               | has shown that spending tim on the surrounding ecosystem
               | can be very valuable (e.g. go fmt, go vet and more
               | recently go fuzz).
        
               | nauticacom wrote:
               | Ah, I understand now. That's a fair point! I agree that
               | the excellent Go tooling is one of its strengths.
        
               | assbuttbuttass wrote:
               | I actually have a different view. One of the things I
               | love about go is it's a simple language, and I can hold
               | the whole language spec in my head while I'm programming.
               | 
               | A generics implementation can't sacrifice the simplicity
               | of the language, or make it any harder to read go code.
        
               | cultofmetatron wrote:
               | lisp and smalltalk both manage this while allowing
               | sophisticated abstractions.
        
               | nauticacom wrote:
               | I can hold the whole language spec in my head while I'm
               | programming
               | 
               | People love to say this about Go, but it's not something
               | that, like, _actually matters_ (and I doubt it 's
               | literally true). A language can be reasonably
               | understandable such that you can effectively and
               | productively program in it without being aggressively
               | simple. Again, to use the case of Ruby, I might not
               | remember every single syntactical construct or handling
               | of every edge case, but the language is reasonably
               | understandable such that I can write programs without
               | constantly asking "what was the syntax for that?" or "how
               | do I express this?" As a counter-example, I think the
               | complexity of C++ is not just limited to its
               | implementation, and leaks out to its interface.
               | ...sacrifice the simplicity of the language, or make it
               | any harder to read go code
               | 
               | These are two separate concerns which, while somewhat
               | related, are not directly correlated. A simple language
               | can make it more obvious which syntactical constructs are
               | being used and what literal operations are being
               | performed, but there are many more dimensions to reading
               | code than just those.
        
               | leshow wrote:
               | I can hold the entire spec to brainfuck in my head, but
               | it doesn't make it any easier to write.
        
               | esprehn wrote:
               | Which part of the JVM is complicated by generics? They're
               | type erased so the VM shouldn't really care. The compiler
               | on the other hand has plenty of complexity...
        
       | FlyingSnake wrote:
       | There are 2 kinds of languages, one that people love to talk
       | about and philosophize about and others that are used in real
       | projects. Golang firmly fits into the 2nd category of languages
       | that are highly opinionated and full of pragmatic choices. It is
       | rare for a language to capture so much mindshare within a decade
       | of it's launch and I'm glad that Go had managed to reach this
       | stage. I am really looking forward to what this new era of Golang
       | brings with it.
        
         | Shadonototra wrote:
         | Exactly, just like firefox / chrome
         | 
         | you hear about firefox everywhere, everyday, and yet only has
         | 3% marketshare
        
         | [deleted]
        
         | Cthulhu_ wrote:
         | I'd add to your first category that there's a lot of languages
         | that adopt features that other languages have, making a ton of
         | languages converge into basically the same language with some
         | caveats. I don't remember the post now but I believe it was
         | posted on HN some time ago, it was pretty insightful.
         | 
         | Anyway yeah, I'm glad Go is resistant to change.
        
           | rob74 wrote:
           | No idea why you are getting downvoted, but I fully agree with
           | that sentiment. There are already enough open source
           | languages who seemingly want to be "everybody's darling" and
           | implement any reasonably sensible feature request. One
           | example: PHP's new "match" expression
           | (https://www.php.net/manual/en/control-structures.match.php).
           | Of course, I can understand that people like Go's more
           | flexible "switch" better than the "traditional" C-style one,
           | but if a language already has the traditional version, does
           | it really have to add a new one which does mostly the same
           | thing and in doing so cause headaches for thousands of
           | developers who use classes or constants named "match"?
        
           | jerf wrote:
           | http://www.jerf.org/iri/post/2908 ?
           | 
           | (BTW, 2011 on that. I would not _today_ agree with the
           | statement  "the Haskell community is the only community I
           | know that is doing new things in the field of language and
           | API design". I think Rust is doing interesting new things
           | now. In 2011 they were still working on basic functionality.
           | There's a couple of other interesting little up-and-coming
           | languages.)
        
         | pydry wrote:
         | They resisted generics since day 1 on the basis of pragmatism.
         | Now they included them on the basis of pragmatism?
         | 
         | I remember something similar with their approach to package
         | management which they said wasnt necessary for years.
         | 
         | They really do seem to resist doing the right thing for as long
         | as possible.
        
           | hbn wrote:
           | I believe I watched a talk from Rob Pike a few years ago
           | where he mentioned that Go didn't have generics, not because
           | they didn't want generics, but because they wanted a Go-like
           | way of doing them, and wanted to spend a lot of time making
           | sure they were done right.
           | 
           | I'm paraphrasing and I wish I had a source for you but I'm
           | pretty confident I didn't make that up.
        
             | pydry wrote:
             | The FAQ said something similar - not that they were
             | vehemently opposed, just that it wasnt a priority.
        
           | kortex wrote:
           | They never resisted generics as a concept. But they refused
           | to implement generics in a way which compromised other Go
           | values. Compilation speed was a big one. It's easier to
           | implement generics if you sacrifice compilation speed (see:
           | c++, rust, and iirc java). To their credit, it took the
           | community a looong time to figure out how pull that off,
           | because it's a _hard problem_. But I think they 've done it.
        
             | esprehn wrote:
             | FWIW Java doesn't sacrifice compiler speed for generics,
             | they're entirely erased at compile time which is cheap.
             | 
             | What they sacrificed was runtime correctness, because the
             | type erasure lets you sneak invalid types into unsuspecting
             | code. How much of a problem that's caused in the real world
             | is debatable.
        
               | inglor wrote:
               | Are you sure you are not mixing up runtime impact with
               | compiler speed? In Java generics are still part of the
               | type system and are type checked which is a non trivial
               | part of the compile time increase in generics typically.
        
           | adamrt wrote:
           | It's not like they just had them ready to go at the flip of a
           | switch and we're just holding out.
           | 
           | There were trade offs and they didn't have a solution on day
           | one.
           | 
           | They've always said they were open to them with the right
           | implementation.
        
           | sacado2 wrote:
           | They weren't ever firmly opposed to generics. Here's the FAQ
           | from 2009:
           | 
           | https://web.archive.org/web/20091113154906/http://golang.org.
           | ..
           | 
           | > Generics may well be added at some point. We don't feel an
           | urgency for them, although we understand some programmers do.
           | 
           | > Generics are convenient but they come at a cost in
           | complexity in the type system and run-time. We haven't yet
           | found a design that gives value proportionate to the
           | complexity, although we continue to think about it.
           | 
           | 12 years later, here they are.
        
             | FlyingSnake wrote:
             | Java was created in 1995 and got generics in JDK 1.5 in
             | 2004, I don't see anyone using this argument against Java.
             | The weird fixation people have about Golang generics is
             | really tiresome, that too after they have added generics
             | after much deliberation.
        
               | masklinn wrote:
               | > Java was created in 1995 and got generics in JDK 1.5 in
               | 2004, I don't see anyone using this argument against
               | Java.
               | 
               | Java was created in an age where very few languages with
               | mainstream relevance had userland generics.
               | 
               | Go was not, and generics had already had to get (somewhat
               | painfully) retrofitted in two of the above.
        
               | DylanSp wrote:
               | Yeah, this. In 1995, about the only mainstream language
               | with generics was C++ with templates. (Same in 2000 when
               | C# was released, incidentally)
               | 
               | When Go came out in 2009, though, Java and C# had pushed
               | generics into the mainstream. Additionally, they'd shown
               | some of the problems with trying to retrofit generics
               | onto a language and ecosystem that didn't previously
               | support them.
        
               | jerf wrote:
               | Having watched this for a while, I would say, my fellow
               | programmers, there's no need to build elaborate
               | psychological defenses for why you don't want to use a
               | language. Just don't use it. There's too many languages
               | to know them all anyhow. You don't have to decide not to
               | use something, then justify your decision with a few
               | comfort blankets that you post every time the topic comes
               | up. Just don't use it, and leave it at that. Or at the
               | very least, skip posting your comfort blankets every time
               | the topic comes up. There's a dozen languages I'd like to
               | know better, and don't use them, and I don't run around
               | giving myself "reasons" I don't learn them. The "reason"
               | is simple: I don't have time. Languages are not an attack
               | on you. Nobody who designed a language was even thinking
               | about you when they created them.
               | 
               | I speak here to those who slag on Go and haven't so much
               | as run "Hello World" in it. Those who _have_ used it,
               | especially for some period of time, and especially those
               | who tried long enough to learn to program Go-in-Go (as
               | opposed to Rust-in-Go or C++-in-Go, etc.), and decided
               | they didn 't like it due to their experience, I invite to
               | continue discussing. You're not who I'm talking about
               | here. Real experiences with the language are valuable
               | contributions.
               | 
               | Those who haven't had real experiences are not making
               | valuable contributions. "Lol generics, lol they realized
               | they're wrong and I was right all along" and "Lol error
               | handling is bad in Go" are not valuable contributions.
        
               | kwertyoowiyop wrote:
               | And of course this opinion is getting downvoted! :-)
        
               | FlyingSnake wrote:
               | This here is the right sentiment, thanks for saying this.
               | I would not bother the internet if my preferred feature
               | is not present in Zig/Nim/Elixir.
        
               | corn_dog wrote:
               | You don't think it contributed at least a little to Go
               | eventually adding generics?
        
               | jerf wrote:
               | No, I don't think the whining did a thing. It may seem
               | impressive on HN, but compared to the continuous stream
               | of whining any successful project receives about all
               | sorts of things I suspect it was weighing less heavily on
               | their mind than HN would think, because it's
               | proportionally much smaller than HN thinks. Also, it's
               | not like Go isn't already fairly successful; if I wrote a
               | language as successful as Go I wouldn't exactly be crying
               | myself to sleep every night, you know?
               | 
               | Cruise through the Go issues and look at all the closed
               | issues. Then, for context, cruise through Rust's or
               | Python's, or your favorite open source project of some
               | size that isn't even a programming language. It's a
               | constant deluge.
               | 
               | What did it was real use cases from using the language
               | for a long time, offered by serious people who weren't
               | just berating the designers. If you read the generics
               | design, and especially if you read the whole history of
               | the design, you can see where this has had an impact,
               | where the features are tuned for the use cases presented
               | by the community, and how the design has changed at least
               | twice in a major way (depending on how you count, of
               | course) as people work through the use cases.
               | 
               | You'll also come to understand better why it's not like
               | you can just flip a switch and "turn on generics" and why
               | everyone running around claiming it was easy is dead
               | wrong. You can also learn some of this by paying
               | attention to discussions of generics in other languages
               | when Go is _not_ a topic, because it 'll become clear
               | when _not_ discussing Go, there 's a lot of broken
               | generics and strange edge cases and poor decisions made
               | by existing languages that we have to live with forever.
               | Not that _all_ of them are broken, but, again, the idea
               | that some care needs to be taken wasn 't something the Go
               | team just made up. There's plenty of languages, even big
               | name languages like Java, that "flipped the switch and
               | turned on generics" and it turned out not to be as
               | awesome as presented, because it's a legitimately hard
               | problem even in 2021.
        
               | pjmlp wrote:
               | In 1995, Standard ML, Ada and Eiffel had generics and
               | were hardly mainstream, C++ templates were still
               | experimental, everything else did not used them.
               | 
               | A tad different from the computing world in 2009.
        
           | neilalexander wrote:
           | Is it really that much of a bad thing to iterate based on
           | real world experience?
        
             | [deleted]
        
             | maleldil wrote:
             | It is when they spend a decade insisting that they right
             | and everyone else was wrong, then ended up doing it anyway.
             | 
             | Generics aren't a cutting edge feature that they wanted to
             | see how it would develop. Their objection against it was
             | ideological.
        
               | neilalexander wrote:
               | I don't really understand this type of criticism. People
               | complained that Go didn't have generics, and now that
               | they've delivered, people still want to complain for some
               | reason.
               | 
               | I can quite believe that the Go team wanted to be sure
               | that the approach made sense for Go, that it was the
               | right solution to the right problem and to keep to their
               | backward compatibility promise. Experience is a good
               | teacher. I really don't know why it matters in the
               | slightest that they didn't arrive at that on day one.
        
               | philosopher1234 wrote:
               | Why are you so bitter about it?
        
           | mseepgood wrote:
           | No, they didn't.
        
       | ianpurton wrote:
       | It's not enough.
       | 
       | As a rust guy I get way more features in the language that help
       | me write error free software.
        
         | Cthulhu_ wrote:
         | Nobody is pushing you to use Go. Nobody is telling you Rust is
         | bad. There is no language war. It's not an either/or. Stick
         | with Rust if you're happy with it, nobody is attacking you over
         | it.
        
         | 1_player wrote:
         | Go write Rust then, what's the problem?
        
         | mfrw wrote:
         | As person who uses both Rust & Go at my $DAYJOB, I would say,
         | both have their merits and demerits, I think, we should view
         | them as tools instead of attaching ourselves to any particular
         | language emotionally. I like to think them as different tools
         | for different use-cases. Use the right tool for the right job.
         | In my opinion, go does an excellent job at networking
         | (TLS/HTTP) & quick cli apps while rust shreds text & does an
         | amazing job at memory management (this is a figurative example;
         | don't drone me if I missed your favorite feature).
        
           | dmart wrote:
           | I often see people recommend Go for CLI apps but I'm not sure
           | why. The built-in `flag` package is really limiting. These
           | days I mostly use Rust with `clap` which is the nicest flag-
           | parsing experience I've found so far in any language.
        
         | diegocg wrote:
         | Go is a very opinionated language that lacks many features on
         | purpose. If you want complex languages Go is definitely not a
         | good choice.
        
         | afr0ck wrote:
         | So, for you, it won't be enough until Go (and possibly every
         | other language that is different from Rust) is "rustified" and
         | turned into a rust-like clone? ... just why?
         | 
         | And BTW, Go is very safe! it has automatic memory management,
         | and managed concurrency for writing bug-free concurrent code.
        
         | usrbinbash wrote:
         | The "lack" of "features" that are prevalent in other languages
         | is a virtue of Go, not a flaw.
        
       | 1_player wrote:
       | Go with generics has definitely surpassed Python for me. Python
       | is good for prototyping but the package management story and the
       | "feel" of the language has ruined it for me. I used to love
       | Python, until I used Django professionally, and the facade
       | crumbled. I'm done with OOP and dynamic typing.
       | 
       | Go felt good, a bit verbose, but my issue was that
       | map/reduce/filter are a much better abstraction over imperative
       | loops, and with generics, the dream of Go with more functional
       | and high-level concepts is closer.
       | 
       | This comment is going to be very controversial, so let me remind
       | you this is my very own opinion.
        
         | rirze wrote:
         | fwiw, I think your experience speaks more to Djanjo and other
         | OOP-inspired packages. Python allows for many different styles
         | of packages to be written... and it's not always a good feature
         | to have.
        
         | Cthulhu_ wrote:
         | Note that you still shouldn't use Go as a functional language
         | (using map/reduce/filter); it's not optimized for functional
         | programming, and the syntax would be pretty gnarly.
         | 
         | A for-loop has what's called "mechanical sympathy", and will go
         | through things in the order that it is in memory. It'll allow
         | the compiler and runtime to manage things quickly through
         | memory, CPU registers, and CPU pipelines.
         | 
         | A great post on the subject is "Why Go Getting Generics Will
         | Not Change Idiomatic Go": http://www.jerf.org/iri/post/2955
        
           | lucian1900 wrote:
           | The bit about "mechanical sympathy" is wrong, though. Plenty
           | of languages inline map/reduce or iterator type code down to
           | very efficient cache-friendly traversal of memory, most
           | notably Rust.
           | 
           | Go's compiler is just particularly naive.
        
             | fsdjkflsjfsoij wrote:
             | > Plenty of languages inline map/reduce or iterator type
             | code down to very efficient cache-friendly traversal of
             | memory
             | 
             | Very few languages outside of Rust and Haskell actually do
             | this reliably and that's including languages like Ocaml and
             | F#. Rust and Haskell are certainly the only even remotely
             | popular languages that do it.
        
               | spekcular wrote:
               | Does Haskell actually succeed here?
               | 
               | This is perhaps not the right way to measure, but: When I
               | last checked the programming language benchmark game [0],
               | the Haskell submissions were basically as fast as
               | C/C++/Rust. _But_ , this came at the cost of writing non-
               | idiomatically/non-functionally - essentially abusing the
               | language to write C in Haskell. I would be curious how
               | well "idiomatic" Haskell compares to C++/Rust, in terms
               | of the compiler optimizing away the functional
               | abstractions.
               | 
               | [0] https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
        
               | igouy wrote:
               | The benchmarks game isn't limited to one Haskell program
               | per task.
               | 
               | Look at both
               | 
               | https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
               | 
               | and
               | 
               | https://benchmarksgame-
               | team.pages.debian.net/benchmarksgame/...
        
               | spekcular wrote:
               | Thanks, that's pretty convincing.
        
               | nine_k wrote:
               | Does the elephant-in-the-room of C++ do it? I thought it
               | does.
               | 
               | I can't bet on what Java and JavaScript JITs make of map
               | / forEach / filter / reduce, but I suspect that they can
               | be pretty efficient, given the clear delineation and the
               | repeated patterns.
        
               | Zababa wrote:
               | I think OCaml can do it with flamba, at least that's what
               | this library readme says: https://github.com/c-cube/iter
               | 
               | > with flambda under sufficiently strong optimization
               | flags, such compositions of operators should be compiled
               | to an actual loop with no overhead!
        
             | kortex wrote:
             | Actually I think while the _compiler_ is a bit naive, the
             | _compiler writers_ are not. They are striving for
             | simplicity, maintainability, speed, etc., vs trying to
             | optimize high-level FP-esque idioms into fast machine code.
             | 
             | The compiler has definitely gotten more optimal over the
             | years, but it's a different beastie than the rust one.
             | Because go is not rust.
        
               | Zababa wrote:
               | Speed and maintainability vs trying to optimize high-
               | level FP-esque idioms into fast machine code is a false
               | dichotomy. OCaml has a really fast compiler, it has been
               | maintained by a small team for 25 years, and it produces
               | fast machine code. A big caveat in comparing OCaml and Go
               | would be multicore support, but it's coming in OCaml,
               | without breaking existing programs and with only a few
               | percent of performance lost.
        
               | lucian1900 wrote:
               | Go is not Rust, but there is a lot it could learn from
               | Rust without sacrifice: sum types, Result for error
               | handling, iterators with for loop support, [edit] non-
               | nullable types etc.
        
               | kortex wrote:
               | I've wanted a Result type I could map over in Go as soon
               | as I saw the idea. But someone recently pointed out,
               | without pattern matching and early return, it's kind of
               | nerfed. Not sure I totally agree (I think it'd still be
               | awesome to have Result, if only for .map()), but I see
               | their point.
               | 
               | I disagree that it would be _without sacrifice_. That 's
               | kind of the whole point.
               | 
               | Unless I'm missing something, go has iterators with for
               | loops.
        
               | lucian1900 wrote:
               | Go switches with exhaustion checks like in [1] would go a
               | long way. An early return construct would be important as
               | well, though, you're right.
               | 
               | Go's for loops can only iterate over builtin types:
               | slices, maps, channels, etc. You can't produce a custom
               | type that is to be iterated over.
               | 
               | 1. https://github.com/BurntSushi/go-sumtype
        
               | sacado2 wrote:
               | Not as simple as it seems. For instance, what is the zero
               | value of a sum type? Let's say, the zero value of a
               | Result<int, error>?
        
               | Lev1a wrote:
               | IIRC in Rust it has to be either of the Ok or Err
               | variants and the enclosed type can then provide its own
               | "zero value" via the standard library "Default" [0] trait
               | or your own implementation for the particular type. That
               | trait is also implemented not for "Result" but for
               | "Option" giving it a default value of "None".
               | 
               | [0]: https://doc.rust-
               | lang.org/std/default/trait.Default.html
        
               | sacado2 wrote:
               | Yes, for Option the default value is quite obvious. I'm
               | talking about Result, because it's the second best-known
               | sum type, and it doesn't have an obvious default value.
        
               | Lev1a wrote:
               | Bindings in Rust have to initialized with an explicit
               | value if the first use comes before the first
               | modification/assignment otherwise [0] you get an error
               | message with error E0381 [1]. Even if that explicit
               | assignment is just through the use of the type's default
               | method [2], if available.
               | 
               | Since it's implemented for Option<T> you can do it the
               | same way [3] for that, but that's not available for
               | Result<T,U> since the semantics are different from Option
               | which is basically just Rust's alternative for
               | 'null'/'nil' (but verifiable by the compiler).
               | 
               | Thus you'd have to _choose_ what variant of the enum you
               | want to have at initialization, after which you can use
               | the Default implementation of the enclosed type, if
               | available (and so on, if there are more nested types).
               | 
               | Though honestly I can't recall using the kind of pattern
               | in Rust that would "need" something like that. Through
               | the handling of code blocks as expressions, early returns
               | etc. you for example don't need to initialize a variable
               | before having an if-/match-/for-/while-/etc. block, you
               | can simply use that block as an expression on the right
               | side of the assignment [4].
               | 
               | [0]: https://play.rust-
               | lang.org/?version=stable&mode=debug&editio...
               | 
               | [1]: https://doc.rust-lang.org/stable/error-
               | index.html#E0381
               | 
               | [2]: https://play.rust-
               | lang.org/?version=stable&mode=debug&editio...
               | 
               | [3]: https://play.rust-
               | lang.org/?version=stable&mode=debug&editio...
               | 
               | [4]: https://play.rust-
               | lang.org/?version=stable&mode=debug&editio...
        
               | [deleted]
        
               | lucian1900 wrote:
               | The zero value of a sum type can be the zero value of the
               | first (or chosen) constituent. In this case, it could be
               | Result<0>.
        
               | sacado2 wrote:
               | I'm not sure that would be any better, in practice, than
               | doing return 0, nil.
        
               | lucian1900 wrote:
               | It would allow functions to be treated generically as
               | returning error-able types. Since some functions even
               | return 3 arguments where the third is the error, this
               | isn't possible today.
               | 
               | It would also allow defer-like syntax to be used on the
               | value a function returns, to return early from the
               | calling function. Rust's ? is an excellent example of
               | this, allowing explicit delegation of error handling that
               | is still very lightweight syntactically.
        
               | kortex wrote:
               | Function composition becomes a lot easier with
               | Result/Option, because you can write functions in terms
               | of assuming a "good" value (not nil/err or otherwise
               | "bad") and then map over it. Or if we really wanna be
               | fancy, flatmap/bind over it.
               | 
               | Foo, err requires either that all receiving functions
               | accept (foo, err), or manually nil-checking at every
               | stage.
               | 
               | Try/catch is the least composable, because deeper error
               | types can "jump out" from any layer. Which means you have
               | to keep wrapping catches, until you hit some base layer
               | you can recover from. You get stack traces, but you lose
               | type information along the way.
               | 
               | Sum (result) and product (foo, nil) types preserve type
               | information. Meaning you can operate more generically
               | over it. Meaning less code duplication.
        
               | kortex wrote:
               | Perfect example of a caveat to "without sacrifice". For
               | context, go really cares about having "zero values" -
               | every initialized variable of some type must have a zero
               | value.
               | 
               | The zero of Error is nil, so logically this would be
               | Result(0, nil). But what do you set the internal state?
               | It's not Ok, cause that int isn't used, and it's not Err
               | either.
               | 
               | Option would work fine though and it would be amazing to
               | map over options instead of nil checks.
               | 
               | I think you'd need to build Result on top of Option, it's
               | naturally kind of ternary - "I have value" "I have error"
               | "idk", either internally or externally.
               | 
               | What might be awesome would be if the Error were a slice
               | type, nil would be "uninitialized" and empty slice means
               | "initialized". still not...pleasant.
        
               | DylanSp wrote:
               | Zero values are definitely an issue, and it'd be hard to
               | get rid of them while sticking to Go's
               | imperative/statement-based style. Still, it'd nice to use
               | an Option type instead of pointers.
        
               | Sharlin wrote:
               | It should be noted, though, that rustc does not really
               | have any particular tricks up its sleeve to optimize
               | functional patterns, or indeed much of anything. A lot of
               | the LLVM IR that rustc generates is _astonishingly_ naive
               | and verbose - largely by design! rustc totally depends on
               | LLVM 's optimization passes to throw out all the
               | boilerplate and output lean and mean optimized machine
               | code.
        
               | kortex wrote:
               | Right but that just means it's LLVM being clever, not
               | rustc.
               | 
               | The main compiler is the self-hosting gc go compiler.
               | Iirc ~~it's the reference implementation~~ erm I guess
               | it's determined by spec, not reference implemenation. Gc
               | is definitely "the default" though.
               | 
               | Then There's the gofrontend, which is a compiler frontend
               | to other compilers, which can work with gcc and llvm. I
               | am not aware of the state of the art for these, but I
               | wonder if there are performance differences.
        
             | mananaysiempre wrote:
             | (The key phrase is "stream fusion".)
        
         | pierrebai wrote:
         | That is a strange sentiment, based on the reasons you've given.
         | Package management on Python with pipenv or poetry have not
         | been an issue in my experience. The other half is kinda hard to
         | pinpoint since "feel" doesn't say much, but is surprising given
         | how clear and powerful the syntax is. I've also taken to use
         | type annotation in Python to ease some of the typing
         | obscurantism of pure dynamic typing.
         | 
         | And python does have map / reduce and much more... so I'm not
         | sure what you mean there.
         | 
         | OTOH, I feel Go and Python are mostly used in quite different
         | domains. To me, Python is the new bash. Go is more for those
         | who dislike C++ and Rust (or Haskell or...) and prefer a
         | certain kind of simplicity.
        
         | throwaway894345 wrote:
         | I like Python the language just fine. Static typing needs a
         | good bit of work, but the real pain points for me have always
         | been performance and tooling (especially package management).
         | 
         | But Go has solid answers for these problems and an excellent
         | static typing story (generics are gravy, but sum types would be
         | nice). I've been very happy with Go on balance.
        
           | metaltyphoon wrote:
           | Expect when you need to use struct tags, then everything is
           | flimsy. I would rather have C#'s attribute over strings only.
        
         | deepsun wrote:
         | > Package management
         | 
         | Are you seriously saying that github.com/somelib is a better
         | package management? Of course nobody forces to use that, but
         | it's what actually been used in most go projects. Even NPM
         | looks better in comparison.
         | 
         | The best quality package management I've seen is Maven,
         | followed by Cargo.
        
           | hellcow wrote:
           | Go has had built-in package management for a while now. It's
           | extremely fast and generates reproducible builds effortlessly
           | in its default behavior in a way I've not experienced before
           | from any other tool.
        
           | angryfeller wrote:
           | npm is just another layer on top of git. go uses git
           | directly. how is that any worse?
        
             | cris-ward wrote:
             | From someone who briefly used 'bower', which was JS
             | dependency management using git, relying on git is a lot
             | worse.
             | 
             | Github repos can vanish, NPM will only let repos be deleted
             | if they have no direct dependencies also on NPM. So you
             | have some guarantees your dependencies wont vanish.
        
               | saturn_vk wrote:
               | If the repo was used at least once, it will be cached by
               | the default proxy. At that point, deleting it will have
               | no effect on builds
        
             | ernst_klim wrote:
             | Does go have some intermediate cache repository between
             | github and enduser?
        
               | uluyol wrote:
               | Yes, https://proxy.golang.org/
               | 
               | You can also configure go to use your own for internal
               | projects or if you just want to avoid the global proxy.
        
           | suddengunter wrote:
           | I disagree
           | 
           | for private Go packages all I need is to point it to another
           | git repo. for nuget/maven etc - I need an artifact registry,
           | with it's own bells and whistles
        
           | mook wrote:
           | As somebody currently working on something that has a mix of
           | Node and Go, I definitely prefer github.com/somelib. In that
           | case there's no worry about package name conflicts (everybody
           | has equally terrible names), so you can always end up doing
           | imports with reasonable names because only the last bit
           | matters. With a single namespace, people can (and do) camp on
           | the obvious names, and often they move on and replacement
           | libraries have to have cute names.
           | 
           | This doesn't mean people _will_ name their things sensibly of
           | course. I've seen golang projects with packages named after
           | gardening, meteorology, and aviation... and each is totally
           | confusing when you're new to it, especially when the naming
           | theme is completely unrelated to what the project actually
           | does.
           | 
           | Here maven would be acceptable (similar to go, there is a
           | domain identifier embedded) whereas cargo (bare words)
           | wouldn't be great.
        
         | maccard wrote:
         | I want to second this. With quick compile times, fat binaries
         | and first class support for crosd compiling, go is suitable for
         | pretty much everything python would be used for. My only use
         | cases for python are as a replacement to bash for shell
         | scripting.
        
           | travisd wrote:
           | Other people point out ML is a use case where Go isn't
           | suitable. And I agree.
           | 
           | But as someone who used to write a LOT of Python, Go has
           | replaced it for anything service or business-logic oriented,
           | and while I do very little data wrangling and machine
           | learning, Julia would be my go to for that. Julia and Go are
           | in, many ways, complementary opposites. If you need to use
           | PyTorch/TensorFlow, okay, fine Python (I'm not going to
           | seriously advocate for just wrapping it all in PyCall.jl
           | unless it's just incidental usage), but Julia is a really
           | strong language for this stuff nowadays.
        
           | kortex wrote:
           | Eh, not really in the data wrangling and machine learning
           | space, at least not quite yet. It's not really amenable to
           | writing libraries for numerical processing - it ends up being
           | super tedious to write something like numpy (you have to
           | implement for every data type, there's at least a dozen+) and
           | nigh-impossible to write an API like pandas, because
           | dataframes are just too dynamic. You _could_ do these things,
           | but it 's just super unpleasant.
           | 
           | I'm hoping generics makes it easier to write things like
           | numpy, without doing `meao_u8`, `mean_u16` etc.
           | 
           | + there's bool, int/uint8,16,32,64, float32/64,
           | complex64/128, that's 13 right there, plus object, a bunch of
           | extended sizes on some architectures, and c-alias types.
        
         | pjmlp wrote:
         | Sorry to break it to you, interfaces are OOP and trace back to
         | Objective-C and Common Lisp Object System protocols or BETA
         | patterns.
        
           | 1_player wrote:
           | I'm talking about Go vs Python, not about the origins of OOP.
        
         | anyfactor wrote:
         | If you don't like Django then you should really try out Flask.
         | It is everything that is right which is wrong about Django and
         | vice versa.
        
         | kortex wrote:
         | I love python, and I don't blame you. I can't stand the Django
         | way of doing things. Everything is so opinionated, dynamic, and
         | magical in the bad way. Pytest has a similar vibe and it drives
         | me nuts. Not a fan of OOP, either, I much prefer immutable
         | objects that are either pure data, or convenience methods that
         | return a copy. No more setters, state mutation methods,
         | setattr, unless it's deeply abstracted away.
         | 
         | Nowadays I use Fastapi, pydantic, Result, and static typing
         | everywhere. Protocol interfaces are great.
        
           | gautamdivgi wrote:
           | This!!! I've done a fair bit of python api development mostly
           | for ML services. We used flask/gunicorn and I'm considering
           | moving to fastapi. I'm sure Django is awesome for what it
           | does well but python has a lot more options.
           | 
           | Fwiw - I do dabble in Go. I've used it for some very targeted
           | systems work where I don't have to install a python
           | interpreter on the target machine and hacking some k8s
           | operators. I really like Go - but the ML ecosystem is pretty
           | heavily python.
        
       | flippinburgers wrote:
       | Never needed in my opinion but here we go...
        
       | akmittal wrote:
       | More than being able to use it I am happy others will stop making
       | jokes about Go
        
         | Debug_Overload wrote:
         | >will stop making jokes about Go
         | 
         | If you seriously think that's gonna happen, you haven't been to
         | Go mockery stations on the interweb.
        
         | tomjen3 wrote:
         | There are languages people don't complain about and languages
         | that people use.
         | 
         | For me, Go is essentially pointless without generics and better
         | error handling (I love that there are no exceptions, but since
         | 99% of the code just return the error anyway, that needs to be
         | the default path), but even with it, it is not much more than C
         | with garbage collection, a few nice features and better syntax
         | in some cases.
         | 
         | So even if it got these problems solved well, I still don't
         | really think I would be using it.
        
         | dgellow wrote:
         | No more complaining about lack of generics, yeah! But you will
         | still have people complaining about error handling in every
         | single discussion about Go
        
           | throwaway894345 wrote:
           | I guarantee we will still hear about how long it took them to
           | add generics to the language and how the language is only
           | popular because of "massive Google marketing campaigns" and
           | how the language is "stuck in 1970" and so on for years to
           | come. People who make silly criticisms aren't likely to be
           | pacified, and I don't think generics will make people less
           | upset that Go is eating into their language's marketshare.
        
             | lowmagnet wrote:
             | I've been using Go since maybe 1.4 and that's only 7 years
             | ago. I started using it as my main language around 2016 or
             | so. I knew people complained about generics and wanted them
             | myself, but the ease of using this language have far
             | outweighed any complaints I've ever had about generics or
             | comma-error or comma-ok patterns that have evolved out of
             | the core design.
             | 
             | I would _love_ some of the proposals surrounding errors to
             | move forward, of course. But I 'm OK with the current
             | state, and will be happier with 1.18.
        
           | latchkey wrote:
           | My all time favorite.
           | https://golang.org/doc/faq#closures_and_goroutines
        
             | amelius wrote:
             | This caveat exists in every language that supports
             | closures, afaict.
        
               | ameliaquining wrote:
               | Java's solution to this problem is maybe the simplest and
               | most elegant: The compiler simply won't let you reassign
               | to a local variable after it's been closed over. I think
               | Go erred by not doing this. (Although I guess it would
               | have complicated things a little because Go has mutable
               | value types, so you'd need to figure out how to handle
               | those.)
        
               | 5e92cb50239222b wrote:
               | Some... _cough_ ... oxidized languages prevent you from
               | doing stupid shit like that. But apparently those
               | languages are too complicated, I'd rather not rely on
               | compiler helping me and keep yet another rule in my head
               | as I'm writing code.
        
               | heheheheheeh wrote:
               | Even if it didnt, I'm sure you'd be able to realize your
               | mistake while you wait 6-8 weeks for you code to compile.
        
               | roblabla wrote:
               | Err, no? Most languages will make a copy for scalar
               | values (e.g. ints), e.g. Javascript and python do that.
               | C++ and Rust go further and provide the user the ability
               | to take the arguments by value or reference, even for
               | classes/structs, which gives you control over what you
               | want. And in this specific case, `v` should be a new
               | instance for each iteration really, it makes very little
               | sense to say that a reference to v of a previous
               | iteration of the loop stays alive for the next iteration.
               | Which is why the program as it exists would be a compile
               | time error in rust, for instance (Maybe in C++ as well,
               | I'm not well-versed enough in the lambda rules of C++).
        
               | jhgb wrote:
               | What does this have to do with values or references? They
               | are orthogonal to scopes, and this example is an issue of
               | scoping. A closure finds free variables in one of its
               | enclosing scopes. If the for loop creates one mutable
               | binding for its control variable, even multiple closures
               | created within the loop's body can all see this single
               | mutable binding because they all share the single
               | environment with this mutable binding in which all of
               | them were created, so they can all observe this binding
               | mutating over time. There are no "arguments by value or
               | reference" because the closure in the example is nullary
               | -- it has no arguments at all.
        
               | ImprobableTruth wrote:
               | They're talking about _capture_ by value or reference. If
               | you use capture by value, created closures will use the
               | value of captured variables at the time the closure is
               | generated.
               | 
               | e.g. in C++, where one has to make capture by reference
               | explicit                   int i = 0;         auto f = [x
               | = i, &y = i] { //x captures i by value, y by reference
               | std::cout << "Value:" << x << ", Reference:" << y;
               | };         i++;         f();
               | 
               | will print out "Value: 0, Reference: 1".
        
               | jhgb wrote:
               | I'm not sure you can call this "a closure". That term has
               | a rather specific meaning related to lexical scoping
               | which simply doesn't deal with copies or references or
               | anything of the kind. There's no "capture by value or
               | reference" since it's not a copy of a value, or even a
               | reference to it -- it's one and the same variable binding
               | inside _and_ outside of the closure (whereas a reference
               | would be another variable name referring to the same
               | value, or at least a differently scoped variable of the
               | same name referring to the same value, but that 's not
               | lexical scoping anymore). To put it bluntly, C++ is
               | faking closures, since without subjecting environments to
               | GC or refcounting, it can't delete the shared
               | environments at just the right time. They just jumped on
               | the bandwagon of closures being fashionable nowadays and
               | tried to emulate closures as closely as possible by
               | constructing artificial automatically generated objects
               | in the background using some syntactic sugar without
               | breaking the existing language.
        
               | ImprobableTruth wrote:
               | I don't really understand your objection. How is
               | 
               | >at least a differently scoped variable of the same name
               | referring to the same value, but that's not lexical
               | scoping anymore
               | 
               | not lexical scoping? That's literally just how closures
               | work under the hood.
               | 
               | And that's exactly why closures have to deal with
               | references (or copies) - every implementation of them is
               | a function pointer and a record for the lexical
               | environment, the latter of which requires that at closure
               | creation time the relevant bindings are captured, either
               | by creating a reference or making a copy.
               | 
               | I also don't understand why C++'s (or Rust's) closures
               | would be 'fake'. If you capture by reference, they work
               | exactly like the closures of other languages. Not having
               | a GC just means you have to be wary of lifetimes. If you
               | use a reference counting pointer (/some other GC'd
               | pointer) you _literally_ have the same closures as other
               | languages.
        
               | jhgb wrote:
               | > How is ... not lexical scoping? That's literally just
               | how closures work under the hood.
               | 
               | In the presence of references in the language, these two
               | cases may be observationally indistinguishable (maybe,
               | I'm not a C++ guru?) but they're still different language
               | features. Lexical scoping does not require taking a
               | reference.
               | 
               | > And that's exactly why closures have to deal with
               | references (or copies)
               | 
               | No, they don't. They deal with bindings. References are
               | either an explicit thing you create (as in, int &b=a; or
               | such), or a parameter passing mechanism...but a free
               | variable is neither (it's not a parameter to the closure
               | in any case), and it exists even in languages with no
               | notion of references whatsoever, such as for example
               | Scheme.
               | 
               | > I also don't understand why C++'s (or Rust's) closures
               | would be 'fake'. If you capture by reference, they work
               | exactly like the closures of other languages. Not having
               | a GC just means you have to be wary of lifetimes.
               | 
               | Yeah, and that's at least one of the things that make it
               | fake. Why would you have to be wary about lifetimes?
               | Closures in languages that support them Just Work(TM).
        
               | earthboundkid wrote:
               | You are wrong about Python. It absolutely does the wrong
               | thing:                   >>> funcs = []         >>> for i
               | in range(10):         ...   def f():         ...
               | print(i)         ...   funcs.append(f)         ...
               | >>> [f() for f in funcs]         9         9         9
               | 9         9         9         9         9         9
               | 9         [None, None, None, None, None, None, None,
               | None, None, None]
        
               | kortex wrote:
               | String is a pointer/slice type under the hood, even if
               | you don't see the asterisk. So when you are passing v,
               | you are passing a reference to a slice which gets updated
               | by the loop. Since the goroutines can run in parallel,
               | you print whatever v is pointing to at the time.
               | 
               | C++ lambdas do the same thing if you pass a pointer.
               | 
               | Python would do the same thing if you had a mutable non-
               | threadsafe objects passed to threads. Eg if you iterate
               | over a list of dicts, and modify the dicts, you'll get
               | the same effect.
               | 
               | So then the question becomes, why does v get re-used,
               | instead of assigning a new pointer each time? Dunno,
               | probably performance. I could see the latter generating a
               | lot of garbage, which can be totally avoided if you don't
               | pass mutable references to goroutines.
               | 
               | What go _really_ lacks IMHO is some kind of _const_
               | modifier for these kind of references. Maybe it does, all
               | I remember are const scalars.
        
               | jhgb wrote:
               | > String is a pointer/slice type under the hood, even if
               | you don't see the asterisk. So when you are passing v,
               | you are passing a reference to a slice which gets updated
               | by the loop. Since the goroutines can run in parallel,
               | you print whatever v is pointing to at the time.
               | 
               | You'll have the same problem with a simple integer (for
               | example, as in https://go.dev/play/p/uqvRoO3ynZt).
               | Nothing to do with v being a reference to something.
        
           | latchkey wrote:
           | Ok then... how about something easier...                 for
           | bar := range list {       }
        
             | Joker_vD wrote:
             | And of course "list" is defined as []int, so you get
             | _really_ peculiar results.
        
           | rob74 wrote:
           | People who are looking for reasons to complain will always
           | find more than enough - in Go and any other language too...
        
         | friedman23 wrote:
         | We wont
        
         | SPBS wrote:
         | Wait til they find out that methods cannot introduce generic
         | parameters. I predict that complaints will shift from 'no
         | generics' to 'no generic methods'.
        
         | rad_gruchalski wrote:
         | Why does one get bothered with that argument anyway? If it
         | works, it works. People who complain are the people who have a
         | problem. But it's a different problem and they don't realise
         | that.
        
           | usrbinbash wrote:
           | Agreed.
           | 
           | There are only 2 kinds of languages: Those people complain
           | about, and those nobody cares about.
        
       ___________________________________________________________________
       (page generated 2021-12-15 23:02 UTC)