Re:Show HN: My notes on Working with Go
by sjroot on Monday August 24, 2020 @09:11AM
(#24260262)
Warning: opinions inbound
I clicked one part (enums) and noticed a pretty glaring issue. The way you are doing enums is really _not_ conventional Go code and probably not something I would allow past a PR review. I’m saying this as someone who has built many production systems with Go and taught it to many devs coming from Java.
So, while I dig a little further, I think it’s fair to warn people to take this with a grain of salt. Use the language yourself and come to your own conclusions as OP did.
Re:Show HN: My notes on Working with Go
by curryst on Monday August 24, 2020 @11:31AM
(#24261609)
What is the advantage of building out enums your way vs OPs? I've done both ways, and I didn't find any situations where one was demonstrably better than the other. Is it that there are no globals? Is it that it's actually constant?
One potential annoyance to me in your design is that there isn't an easily accessible map of enum values and their string representation. That is really useful for testing; most of my enums end up with a .Validate() method that checks whether the underlying value is actually a valid member of the enum. If I have that map, it's trivial to right a test that iterates over enum keys and ensure that a) valid keys pass Validate(), and b) enum.String() returns the corret string. Enums (theoretically) shouldn't be modified at runtime, so it should be perfectly safe and valid to have a single, global instance of that data.
I thought the use of maps to store the enum keys/values was odd, but when I thought about it, maps allow the enum keys to be sparse, which can be valuable.
Re:Show HN: My notes on Working with Go
by sjroot on Monday August 24, 2020 @01:16PM
(#24262855)
First off, I should clarify that I'd actually love to see Go add support for proper enums, as I've certainly found it lacking.
My biggest issues would be maintainability and, as you mentioned, using global maps. If your enum itself is not a string value, but you NEED a string representation, then it should just implement `Stringer`.
As far as maintainability:
- The naming convention used here is not consistent with how enums are named in Go. For a good example, see the HTTP package, specifically request methods and response status codes [1]. Really, it isn't even an appropriate naming convention for constant values in any language, with `UPPERCASE_UPPERCASE_minor_note`, it looks a bit silly and took longer for me to grok.
- What if I want to add a new enum variant? I seriously have to add it to three different places? If I start touching this map in places outside the original source file, things will get really ugly really fast.
- A bit nit-picky, but: why use an `int32` here?
This file, in my opinion, is over-engineered. Go code should be simple; many people learning Go for the first time hesitate to work that way, unfortunately.
Other common issues I see with people learning Go for the first time:
- Overuse of concurrency. People like to use the `go` statement wherever possible, and create overly-complex APIs with channels. Unless you have multiple events that need to be done in parallel, yet simultaneously needing to communicate between them, you should not use them in your package's public API. Let your package consumers choose when to make that call.
- Package structure, particularly in modules. People like `src` directories, but Go doesn't work that way. Your top priority as someone learning Go should be to dig through Go's standard library itself and see how it is organized.
Re:Show HN: My notes on Working with Go
by ed25519FUUU on Monday August 24, 2020 @02:56PM
(#24264071)
> Overuse of concurrency. People like to use the `go` statement wherever possible, and create overly-complex APIs with channels. Unless you have multiple events that need to be done in parallel, yet simultaneously needing to communicate between them, you should not use them in your package's public API. Let your package consumers choose when to make that call.
Agree. As much as possible, always leave it up to your caller on whether or not you want the blocking calls to run concurrently. Over-use of `go` as well as unnecessarily buffered channels are two really common anti-patterns with new Go developers.
And don't get me wrong, they're not breaking or absolutely terrible design choices, it's just that they're choices you typically wouldn't make after spending quality time writing apps with the language.
Re:Show HN: My notes on Working with Go
by heleninboodler on Monday August 24, 2020 @05:07PM
(#24265526)
> If your enum itself is not a string value, but you NEED a string representation, then it should just implement `Stringer`.
I don't understand. Isn't this exactly what they did?
The only actual problem I see with this enum implementation is that the module-level value->string map is module public, which should definitely be fixed. Other than that, this looks like a bog-standard enum implementation with slightly odd internal naming conventions.
> I seriously have to add it to three different places?
Well, come on, now. The idiomatic example has two places to edit as well, and the third place here is for functionality the idiomatic example doesn't have (mapping back from string to value). You could always generate this map at runtime in an init() function but I suspect some would complain about that as well.
Re:Show HN: My notes on Working with Go
by arwineap on Monday August 24, 2020 @10:55AM
(#24261265)
I use this pattern without iota; tending towards constants as strings. This allows it to "serialize" to strings nicely instead of exposing useless (without context) integers
Re:Show HN: My notes on Working with Go
by colesantiago on Monday August 24, 2020 @09:52AM
(#24260625)
> So, while I dig a little further, I think it’s fair to warn people to take this with a grain of salt. Use the language yourself and come to your own conclusions as OP did.
I'm sure with the experience you have with Go, you can open a pull request to their notes to fix this issue.
The code in the section labeled Enums looks like it is straight out of the Protobuf compiler. grpc is referenced later on, so that structure pattern may be related.
Re:Show HN: My notes on Working with Go
by likeabbas on Monday August 24, 2020 @12:40PM
(#24262388)
I really enjoyed using Go in my Distributed Systems course in college, and I've enjoyed using it as a replacement for Python for little scripts I've written since the typed aspect of it makes it easier for me to go back and read what I've done. But, I have not enjoyed the Go micro service we use at work. We went with Go thinking the coroutine thread implementation would significantly improve performance over a Java microservice, but the service turned out to be GC limited. And the overall lack of support for most language features has made this codebase much larger than it needed to be.
I wish I could convince my team to try Rust for our next service
Re:Show HN: My notes on Working with Go
by derefr on Monday August 24, 2020 @12:49PM
(#24262505)
> but the service turned out to be GC limited
Go indeed has a lousy GC (compared to the JVM, at least.) This is why, in most production Go codebases I've seen, there's heavy reliance on https://golang.org/src/sync/pool.go (or a NIH knocked-together version of it, if the author doesn't realize sync/pool exists.)
Try just switching a few of your most-oft-called constructors to allocate from a pool. It's pretty much the lowest-hanging fruit for Go performance gains.
- the cheat sheet differentiates between 'declaring' and 'declaring and initializing', but in Go there are no uninitialized arrays (or slices)
- a lot of times in this file, a slice is created instead of an array (lines 18, 21, 25, 31)
- arrays in Go don't really have a capacity (it's always the same as the array's length)
- the built-ins append and copy as well as the sort functions don't accept arrays (I assume this is why slices are created?)
Re:Show HN: My notes on Working with Go
by axaxs on Monday August 24, 2020 @02:24PM
(#24263712)
> in Go there are no uninitialized arrays (or slices)
This is a little murky and misleading. In Go, you can actually save memory by 'declaring' only. For example, if you do var x []string, and never use x, it never actually uses memory. Whereas x := []string{} does. The JSON encoder treats the two differently, as well.
Re:Show HN: My notes on Working with Go
by yencabulator on Monday August 24, 2020 @04:50PM
(#24265347)
Much like the github link, you're confusing slices with arrays. Slices can be nil (data=nil, len=cap=0) or non-nil (data points somewhere, len and cap are what they are), but arrays are just arrays, there's no such thing as an uninitialized [3]byte.
Re:Show HN: My notes on Working with Go
by amscanne on Tuesday August 25, 2020 @02:38AM
(#24268657)
I believe your comment is wrong though. Those two things will use exactly the same amount of memory.
The data pointer in the slice points to an array-type of size zero. All allocations for objects of size zero return a fixed address in the data section (so there is a distinction between a nil and non-nil object, but a pointer to a zero sized object does not actually take any space).
Re:Show HN: My notes on Working with Go
by axaxs on Tuesday August 25, 2020 @12:23PM
(#24273003)
Flip the first line between true and false, you'll see different memory usage based on declaration type. I haven't analyzed the compiler code, but my assumption is it's forced to return an actual slice object when one is declared with :=. But I'd be happy to be better educated here -
Re:Show HN: My notes on Working with Go
by amscanne on Wednesday August 26, 2020 @01:32PM
(#24284860)
This is a total red herring.
I don't know why the numbers are consistently different for the different programs, but the compiler is completely optimizing out the function call in both cases.
Re:Show HN: My notes on Working with Go
by yencabulator on Tuesday August 25, 2020 @08:08PM
(#24277724)
[]int{} is a non-nil slice, which allocates. The zero-length optimization probably doesn't exist for arrays in this context, because no sane code does this.
This still has nothing to do with "declaring" vs "initializing" (Go makes no such distinction; all values are always "initialized"), or direct use of arrays.
Re:Show HN: My notes on Working with Go
by amscanne on Wednesday August 26, 2020 @01:21PM
(#24284704)
> The zero-length optimization probably doesn't exist for arrays in this context
This is no distinction for arrays for non-array. E.g. [0]int is a valid type, and it's size is zero. It is treated exactly the same as all other zero-sized types. This is not a special optimization: there are may cases of zero-sized types.
The slice itself is a value type. So foo := []int{} would occupy 24-bytes (data pointer, len, cap) and not necessarily escape to the heap, exactly the same as var foo []string.
I think it's more geared towards people who have experience in one language and want to get a quick crash course in another. Most useful for people who learn by example.
Re:Show HN: My notes on Working with Go
by throwaway894345 on Monday August 24, 2020 @09:54AM
(#24260652)
I started with Java, C#, and Python and one thing I really appreciated about Go was the simplicity. I like how many features it strips from C#. Some people take the tack that a language that is the union of all features is the best possible language on the grounds that one can choose their own feature set, but this is pretty obviously fallacious when you consider that you need to collaborate with others, use 3rd party libraries, etc. I also like the fact that it compiles to a single static binary by default.
Don't get me wrong, I think C# and .Net in general are pretty cool pieces of technology, but I never find myself reaching for them because I'm very often confident that I can get the job done more quickly with Go.
Re:Show HN: My notes on Working with Go
by The_rationalist on Monday August 24, 2020 @10:18AM
(#24260889)
Just don't use the features you haven't yet learn.
In a few years of experience you will reach a plateau of productivity in go that you'll only be able to beat by migrating toward a more featureful/better thought language
Re:Show HN: My notes on Working with Go
by throwaway894345 on Monday August 24, 2020 @11:25AM
(#24261546)
Like I said, I came to Go from C#, and my experience has been such that I’m generally more productive in Go. Further, I already addressed the fallacy that you can just avoid certain features.
Re:Show HN: My notes on Working with Go
by cmckn on Monday August 24, 2020 @12:40PM
(#24262393)
Vast majority of my experience is Java, but I'm in a C# role right now. I have to agree with you, having only used Go tangentially -- the tooling is more approachable and bootstrapping a project is more straightforward. I can go ;) from zero to _something_ in a much shorter time
Re:Show HN: My notes on Working with Go
by throwaway894345 on Monday August 24, 2020 @01:28PM
(#24263018)
This is what drew me to Go circa 2012, and I’ve been pleased to find that Go’s value proposition doesn’t end after a short period of time but continues to pay dividends for individual developers and for the project as a whole over the long term.
Re:Show HN: My notes on Working with Go
by throwaway894345 on Monday August 24, 2020 @07:47PM
(#24266768)
Productivity isn’t the only factor. C# and Kotlin are great languages in their own right. Notably for very dynamic workloads, the respective JIT compilers can do some impressive optimizations.
Re:Show HN: My notes on Working with Go
by zeroc8 on Monday August 24, 2020 @02:25PM
(#24263720)
Every developer on the project then uses his favorite subset. Which may or may not be the same one you prefer and know. Unless of course you know everything ;)
Re:Show HN: My notes on Working with Go
by mylinkedlist on Monday August 24, 2020 @01:54PM
(#24263328)
My work involves a lot of AWS infra related things. Some time ago, I was tasked with finding a way to route websocket requests to the backend, which is completely dynamic. While I was looking for solutions, I came across posts here in HN about creating simple reverse proxies using Go. This got me interested in Go. I felt Go would be an ideal language for networking related work. Note that I am a complete newbie in all these, so could be wrong.
Re:Show HN: My notes on Working with Go
by oldgun on Monday August 24, 2020 @11:53AM
(#24261825)
Thanks for the work. It's quite some materials to compile. I love how you organize your thoughts and knowledge together and I've just started doing that too.
Re:Show HN: My notes on Working with Go
by dang on Tuesday August 25, 2020 @05:37PM
(#24276446)
Please don't post unsubstantive comments to HN, and please don't do programming language flamewars here. They're tedious and shallow and usually turn nasty.. We're hoping for something more interesting on this site.
Re:Show HN: My notes on Working with Go
by dang on Tuesday August 25, 2020 @05:38PM
(#24276457)
The HN guidelines include a version of please don't feed the trolls. It goes like this: "Don't feed egregious comments by replying; flag them instead."
Re:Show HN: My notes on Working with Go
by hombre_fatal on Monday August 24, 2020 @05:25AM
(#24258861)
Do we really need to entertain throwaway accounts created just for the boring "lang {good,bad}!" interjection?
If you want to see it, there are so many places we have that discussion. And that discussion can be found so many times online. Look at any Go version release on HN if you want to find more.
Even making a top-level comment like "Can anyone explain some quick pros/cons of $lang?" would go farther than these interjections where we need to prod them with twenty questions just to help them flesh out their own point of view. That's what's annoying about it.
Re:Show HN: My notes on Working with Go
by bruhlollol on Monday August 24, 2020 @05:12AM
(#24258789)
It ignores some historical bad design decisions, the worst of them being having null in the language, the famous one billion dollar mistake. And well, no support for functional/immutable data structures is something I dislike. My squad did a micro-service in Go at work and was not pleasant as we expected.
Re:Show HN: My notes on Working with Go
by Insanity on Monday August 24, 2020 @07:40AM
(#24259675)
Mh, so you wrote one micro-service and came to that conclusion? What did you do to learn the language beforehand?
For what it's worth, I've been programming with Go professionally for a few years, and I do agree with the "null" issue. Although in practice - with a good development culture - it's less of a problem than you might think initially. We tend to avoid using pointers (because, they're not even faster than structs in _many_ instances. They don't work like pointers in C/C++).
By avoiding pointers you also avoid `nil` being a thing. but if not having nil is a strict requirement I'll pick another language like Haskell instead. Pick the right tool for the job yada yada
Re:Show HN: My notes on Working with Go
by throwaway894345 on Monday August 24, 2020 @09:59AM
(#24260684)
I'm a big fan of ML-like type systems, but I never understand why Go gets so much more grief than Python, JS, etc for having nil. At least in Go, only reference types can be nil as opposed to literally any variable. Same with conversation about generics: "How can anyone write software in a language without [type-safe] generics?" of course lots of profitable software is written in languages with no type safety whatsoever and that doesn't seem to bother people.
Re:Show HN: My notes on Working with Go
by AnimalMuppet on Monday August 24, 2020 @01:39PM
(#24263147)
I think that it doesn't bother people when a non-type-safe language isn't type safe. If you reach for Python, you know what you're getting. But when a type-safe language is type-safe-except-for-X, that bothers people who wanted a type-safe language.
And it's one thing if the except-for-X is "except for conversions", like casts in C, C++, and Java. Non-type-safe generics aren't usually a place where you are deliberately bypassing the type safety; they're a place where you'd like to have the type safety you have everywhere else in the language.
Re:Show HN: My notes on Working with Go
by throwaway894345 on Monday August 24, 2020 @03:52PM
(#24264742)
I don’t buy this at all. No one finds out that Go lacks generics when they’re neck deep in a project, it’s widely known ahead of time. If you need something that is type-safe >95% of the time, Go isn’t the answer (yet, anyway) and you rule it out before the first line of code is written and move on to other languages (of course, lots of life-or-death applications are written in C which has a weaker type system than Go, so I would also be skeptical about applications that need >95% type safety).
Re:Show HN: My notes on Working with Go
by isatty on Monday August 24, 2020 @05:48AM
(#24259007)
It depends on _for what_. The most important part of these discussions often leaves out this important part.
I use go as a python replacement for the most part and it’s brilliant at it. Types, compiled, good collection of external libraries and easy to read. For most of my scripting or mini projects I’m not willing to use C++ and by the same thought, I’m not willing to use rust either.
Re:Show HN: My notes on Working with Go
by vips7L on Monday August 24, 2020 @06:35AM
(#24259278)
While I am no fan of Go, Rust is not a better alternative for most use cases of the average Go program. A better alternative would more likely be Java/Kotlin/Scala/C#. All with proper generics, good standard libraries/ecosystems, and fast run times.
Re:Show HN: My notes on Working with Go
by tfigment on Monday August 24, 2020 @09:24AM
(#24260378)
.Net Core compiles to native and can be packaged to not need common runtime installed. And targets linux. You can even have it create a single file executable though admittedly it unpacks to temp folder at runtime if you do this. Down side is everything is like 80 MB minimum if you do this.
Re:Show HN: My notes on Working with Go
by erik_seaberg on Tuesday August 25, 2020 @12:24AM
(#24268115)
To be fair, it's possible to write code that does no heap allocation in each of these languages. None of them guard against mistakes that create GC work, and Java would not be my choice for this.
Re:Show HN: My notes on Working with Go
by Cthulhu_ on Monday August 24, 2020 @05:36AM
(#24258942)
Null is only a thing for pointers, in a lot of cases you can use value types where they use a sane "zero" value for everything by default.
But did you really create a new troll account to go and represent the Rust Evangelism Squad? I mean if you really want to discuss the merits of Rust vs Go, at least have the decency to do a writeup that doesn't repeat the same - known - issues with Go.
Re:Show HN: My notes on Working with Go
by bruhlollol on Monday August 24, 2020 @06:08AM
(#24259134)
I am not evangelist. Go error handling and pointers could be type safe, that's my real disappointment with it. I like its simplicity, but having a sane zero value for "almost everything" doesn't solve the problem.
Re:Show HN: My notes on Working with Go
by cy_hauser on Monday August 24, 2020 @09:21AM
(#24260356)
My first click was the link for "Accessing a value of an unexported identifier". Figured I'd see some reflection trick or similar. In looking at that code I still have no idea what it's doing in relation to accessing an unexported identifier.
So I went to the next link down, "Unexported fields from an exported struct". Figured this would be the clever way to access the "message" field. But again I don't get it. It seems it's the same code as the last example.
This either says something about my ability to understand Go code or that maybe a bit more exposition would be useful for at least some of the examples.
I clicked one part (enums) and noticed a pretty glaring issue. The way you are doing enums is really _not_ conventional Go code and probably not something I would allow past a PR review. I’m saying this as someone who has built many production systems with Go and taught it to many devs coming from Java.
This guide is more in-line with how Go enums should be designed: https://blog.learngoprogramming.com/golang-const-type-enums-...
So, while I dig a little further, I think it’s fair to warn people to take this with a grain of salt. Use the language yourself and come to your own conclusions as OP did.
One potential annoyance to me in your design is that there isn't an easily accessible map of enum values and their string representation. That is really useful for testing; most of my enums end up with a .Validate() method that checks whether the underlying value is actually a valid member of the enum. If I have that map, it's trivial to right a test that iterates over enum keys and ensure that a) valid keys pass Validate(), and b) enum.String() returns the corret string. Enums (theoretically) shouldn't be modified at runtime, so it should be perfectly safe and valid to have a single, global instance of that data.
I thought the use of maps to store the enum keys/values was odd, but when I thought about it, maps allow the enum keys to be sparse, which can be valuable.
My biggest issues would be maintainability and, as you mentioned, using global maps. If your enum itself is not a string value, but you NEED a string representation, then it should just implement `Stringer`.
As far as maintainability:
- The naming convention used here is not consistent with how enums are named in Go. For a good example, see the HTTP package, specifically request methods and response status codes [1]. Really, it isn't even an appropriate naming convention for constant values in any language, with `UPPERCASE_UPPERCASE_minor_note`, it looks a bit silly and took longer for me to grok.
- What if I want to add a new enum variant? I seriously have to add it to three different places? If I start touching this map in places outside the original source file, things will get really ugly really fast.
- A bit nit-picky, but: why use an `int32` here?
This file, in my opinion, is over-engineered. Go code should be simple; many people learning Go for the first time hesitate to work that way, unfortunately.
Other common issues I see with people learning Go for the first time:
- Overuse of concurrency. People like to use the `go` statement wherever possible, and create overly-complex APIs with channels. Unless you have multiple events that need to be done in parallel, yet simultaneously needing to communicate between them, you should not use them in your package's public API. Let your package consumers choose when to make that call.
- Package structure, particularly in modules. People like `src` directories, but Go doesn't work that way. Your top priority as someone learning Go should be to dig through Go's standard library itself and see how it is organized.
[1] https://golang.org/pkg/net/http/#pkg-constants
Agree. As much as possible, always leave it up to your caller on whether or not you want the blocking calls to run concurrently. Over-use of `go` as well as unnecessarily buffered channels are two really common anti-patterns with new Go developers.
And don't get me wrong, they're not breaking or absolutely terrible design choices, it's just that they're choices you typically wouldn't make after spending quality time writing apps with the language.
1st way: the way our Java devs thought Go was “supposed” to be written
2nd way: how Go should probably actually be written
By embracing the simplicity and Go’s opinionatedness the first time around, you’ll save yourself a lot of refactoring headache later.
I don't understand. Isn't this exactly what they did?
The only actual problem I see with this enum implementation is that the module-level value->string map is module public, which should definitely be fixed. Other than that, this looks like a bog-standard enum implementation with slightly odd internal naming conventions.
> I seriously have to add it to three different places?
Well, come on, now. The idiomatic example has two places to edit as well, and the third place here is for functionality the idiomatic example doesn't have (mapping back from string to value). You could always generate this map at runtime in an init() function but I suspect some would complain about that as well.
Do you have any thoughts on iota vs strings?
I'm sure with the experience you have with Go, you can open a pull request to their notes to fix this issue.
The code in the section labeled Enums looks like it is straight out of the Protobuf compiler. grpc is referenced later on, so that structure pattern may be related.
TLDR: Before going down that route, you should make sure you really REALLY need them. Someone learning Go for the first time probably doesn't.
I wish I could convince my team to try Rust for our next service
Go indeed has a lousy GC (compared to the JVM, at least.) This is why, in most production Go codebases I've seen, there's heavy reliance on https://golang.org/src/sync/pool.go (or a NIH knocked-together version of it, if the author doesn't realize sync/pool exists.)
Try just switching a few of your most-oft-called constructors to allocate from a pool. It's pretty much the lowest-hanging fruit for Go performance gains.
- the cheat sheet differentiates between 'declaring' and 'declaring and initializing', but in Go there are no uninitialized arrays (or slices) - a lot of times in this file, a slice is created instead of an array (lines 18, 21, 25, 31) - arrays in Go don't really have a capacity (it's always the same as the array's length) - the built-ins append and copy as well as the sort functions don't accept arrays (I assume this is why slices are created?)
This is a little murky and misleading. In Go, you can actually save memory by 'declaring' only. For example, if you do var x []string, and never use x, it never actually uses memory. Whereas x := []string{} does. The JSON encoder treats the two differently, as well.
The data pointer in the slice points to an array-type of size zero. All allocations for objects of size zero return a fixed address in the data section (so there is a distinction between a nil and non-nil object, but a pointer to a zero sized object does not actually take any space).
See line 909: https://golang.org/src/runtime/malloc.go
https://play.golang.org/p/wVyv0qhj9rp
I don't know why the numbers are consistently different for the different programs, but the compiler is completely optimizing out the function call in both cases.
Consider the example where you do two prints: https://play.golang.org/p/Y1GUutEQkzx
Here is the compiled object code, which is identical for true and false: main.go:15 0x49b640 64488b0c25f8ffffff MOVQ FS:0xfffffff8, CX main.go:15 0x49b649 483b6110 CMPQ 0x10(CX), SP main.go:15 0x49b64d 7624 JBE 0x49b673 main.go:15 0x49b64f 4883ec08 SUBQ $0x8, SP main.go:15 0x49b653 48892c24 MOVQ BP, 0(SP) main.go:15 0x49b657 488d2c24 LEAQ 0(SP), BP main.go:16 0x49b65b 0f1f440000 NOPL 0(AX)(AX*1) main.go:16 0x49b660 e89bfeffff CALL main.printStats(SB) main.go:21 0x49b665 e896feffff CALL main.printStats(SB) main.go:22 0x49b66a 488b2c24 MOVQ 0(SP), BP main.go:22 0x49b66e 4883c408 ADDQ $0x8, SP main.go:22 0x49b672 c3 RET
Notice how there's nothing between the printStats calls?
This still has nothing to do with "declaring" vs "initializing" (Go makes no such distinction; all values are always "initialized"), or direct use of arrays.
This is no distinction for arrays for non-array. E.g. [0]int is a valid type, and it's size is zero. It is treated exactly the same as all other zero-sized types. This is not a special optimization: there are may cases of zero-sized types.
The slice itself is a value type. So foo := []int{} would occupy 24-bytes (data pointer, len, cap) and not necessarily escape to the heap, exactly the same as var foo []string.
If anyone knows similar notes for Python & C#, please reply.
I think it's more geared towards people who have experience in one language and want to get a quick crash course in another. Most useful for people who learn by example.
(I don't mean ill to the original author, they present it as such. Just saying that here.)
Don't get me wrong, I think C# and .Net in general are pretty cool pieces of technology, but I never find myself reaching for them because I'm very often confident that I can get the job done more quickly with Go.
https://news.ycombinator.com/newsguidelines.html
https://news.ycombinator.com/newsguidelines.html
If you want to see it, there are so many places we have that discussion. And that discussion can be found so many times online. Look at any Go version release on HN if you want to find more.
Even making a top-level comment like "Can anyone explain some quick pros/cons of $lang?" would go farther than these interjections where we need to prod them with twenty questions just to help them flesh out their own point of view. That's what's annoying about it.
For what it's worth, I've been programming with Go professionally for a few years, and I do agree with the "null" issue. Although in practice - with a good development culture - it's less of a problem than you might think initially. We tend to avoid using pointers (because, they're not even faster than structs in _many_ instances. They don't work like pointers in C/C++).
By avoiding pointers you also avoid `nil` being a thing. but if not having nil is a strict requirement I'll pick another language like Haskell instead. Pick the right tool for the job yada yada
To be fair, that's a lot more empiricism than some teams use.
And it's one thing if the except-for-X is "except for conversions", like casts in C, C++, and Java. Non-type-safe generics aren't usually a place where you are deliberately bypassing the type safety; they're a place where you'd like to have the type safety you have everywhere else in the language.
I use go as a python replacement for the most part and it’s brilliant at it. Types, compiled, good collection of external libraries and easy to read. For most of my scripting or mini projects I’m not willing to use C++ and by the same thought, I’m not willing to use rust either.
I've had success deploying native services using Quarkus [0] for Java.
Additionally in modern java you would use jlink [1] to produce a minimal jvm image that ships with your application. No need to install.
[0] https://quarkus.io/
[1] https://docs.oracle.com/en/java/javase/11/tools/jlink.html
Edit Phone auto-correct from memory management to measurement.
I'm still not convinced by this statement.
But did you really create a new troll account to go and represent the Rust Evangelism Squad? I mean if you really want to discuss the merits of Rust vs Go, at least have the decency to do a writeup that doesn't repeat the same - known - issues with Go.
So I went to the next link down, "Unexported fields from an exported struct". Figured this would be the clever way to access the "message" field. But again I don't get it. It seems it's the same code as the last example.
This either says something about my ability to understand Go code or that maybe a bit more exposition would be useful for at least some of the examples.
So in the end there's really no trick, you still can't access them directly.
would be useful to somebody, seems like a good idea to me.