
Show HN: My notes on Working with Go - betty200744
https://github.com/betty200744/ultimate-go
======
sjroot
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.

This guide is more in-line with how Go enums should be designed:
[https://blog.learngoprogramming.com/golang-const-type-
enums-...](https://blog.learngoprogramming.com/golang-const-type-enums-iota-
bc4befd096d3)

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.

~~~
arwineap
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

Do you have any thoughts on iota vs strings?

~~~
sjroot
I typically use strings for enum values as well.

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

~~~
derefr
> 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](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.

~~~
likeabbas
Right, but if we go with Rust we won’t have to worry about GC issues

------
sauerbraten
I checked out the example code for arrays
([https://github.com/betty200744/ultimate-
go/blob/3de8a053d9f7...](https://github.com/betty200744/ultimate-
go/blob/3de8a053d9f70523af709b4f320f18a5bd0b0c2e/Language_Specification/reference-
type/array/arrays.go)) and noticed that OP seems to misunderstand a few things
about Go arrays:

\- 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?)

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

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

~~~
axaxs
I'm not. I've been a Go programmer for years, and I literally quoted your
comment above mine - it says (or slices)

~~~
amscanne
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).

See line 909:
[https://golang.org/src/runtime/malloc.go](https://golang.org/src/runtime/malloc.go)

~~~
axaxs
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 -

[https://play.golang.org/p/wVyv0qhj9rp](https://play.golang.org/p/wVyv0qhj9rp)

~~~
yencabulator
[]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.

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

------
mylinkedlist
Thank you. I am just beginning to learn Go. This will be very useful to me.

If anyone knows similar notes for Python & C#, please reply.

~~~
The_rationalist
What make you keep learning Go once you've tasted C# delights?

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

~~~
The_rationalist
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

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

~~~
cmckn
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

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

------
hujun
good stuff, there is another really good GO online book: Go
101,[https://go101.org/](https://go101.org/) a lot of details, has been really
helpful for me to advance in Go

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

------
0xdeadbeefbabe
Is if err != nil supposed to become if err.Type.something != thatType?

------
mesaframe
It's just code with comments what code is doing. Can we call them notes?

~~~
bouncycastle
Go is very readable. It seems I can understand what he's doing / means, even
with Chinese comments!

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

~~~
bouncycastle
For that, you will need to know a bit about Go. The full totorial is here
[https://www.ardanlabs.com/blog/2014/03/exportedunexported-
id...](https://www.ardanlabs.com/blog/2014/03/exportedunexported-identifiers-
in-go.html)

So in the end there's really no trick, you still can't access them directly.

------
pc86
Please have commit messages more informative than "update $filename"

~~~
sjroot
Please try to contribute something actually relevant to the post.

