
Learn Go: Hand-crafted Go exercises and examples - inancgumus
https://github.com/inancgumus/learngo
======
slimsag
Observation: I see that you do 26 exercises before doing anything with
pointers.

I often wonder if one of the reasons Go is more "simple" or approachable to
some is because you can, to a large extent, ignore pointers and interfaces and
"just write that weird little * or & in some places" and get away with it.
Whereas, I believe in other languages, this is much less possible (e.g. in
Java or Rust you need to learn about less "just logic" traits of the language
earlier on (class inheritance, generics or Options, borrow checking, etc.)

I'm not saying the above is a good thing, but I often wonder if there aren't
ways to make this more of an incremental learning curve in other languages in
a similar way that you can largely ignore pointers in Go for a long time and
be productive without understanding them. What would a similar incremental
learning curve for generics be?

~~~
littlestymaar
Your can't really do anything real without pointers in Go though because you
won't be able to mutate states out of a function.

~~~
slimsag
That's definitely true, but I've often seen beginners just say:

    
    
        type Foo struct { ... }
        func (f *Foo) Bar() { ... }
    

And go "Aha, that's an object and a method, I get it!" but when asked whether
they should be using a pointer there or not, have no idea what that even
entails.

In other words, it's possible to neglect the details of pointers easily and
have things generally work

~~~
hitsurume
This is me right now. I get the basics of Go, but I don't understand when i'm
suppose to have something be a pointer, and when i'm suppose to use * or & .
Anyone who has a good explanation in a EL5 way, would help me a lot!!

~~~
sacado2
Imagine we're working together and I have some text document I want you to
work on and update. If I send you the text by email, I send a _copy_ of it
(the original text is still on my computer). If you modify that copy and keep
it for you, I won't ever know what you did. I just used a function

    
    
        func (c Coworker) SendForUpdates(d Document) {
            ...
        }
    

That wouldn't make sense. You worked hard and I don't even know what you did.
So, what I would expect you to do is, once you made updates on the copy, to
send me back that copy by email. That would be akin to

    
    
        func (c Coworker) SendForUpdates(d Document) Document {
            ...
            return d
        }
    

I sent you a copy, and you returned another updated copy. That is "pass-by-
value", the default, no-pointer style.

Now, let's say I think those emails back and forth and boring. Rather than
sending you a copy of the text each time, I could rather use Google Docs, and
send you the _link_ to that document. Its URL, rather than a copy of its
content. Now, you can just go to that URL and do the updates on the document.
You don't have to send me back the document: you're working on it, not on a
copy of it! Well, that URL is a reference to the document rather than the
document itself, or, if you prefer, a _pointer_ to it. So, now, the function
would be

    
    
        func (c Coworker) SendForUpdates(d *Document) {
            ...
        }
    

And we're done, no more back-and-forth dance now! That is "pass-by-reference".

You don't only use "pass-by-reference" just to be able to check updates on the
document sent, by the way. If I want to send you some text just for your
information and I don't expect any kind of update, I'll use pass-by-value (the
very first function). But what if I want to send you a 3 GB video? I can't
send that through e-mail! Sending a copy would be totally inefficient. Once
again, I'll send you a pointer, an URL to download the video:

    
    
        func (c Coworker) InformText(d Document) // d is small: pass-by-value
    
        func (c Coworker) InformBigVideo(v *Video) // videos are huge: pass-by-reference
    

Why not use pointers everywhere by default, they seem easier, right? That's
basically what java and python do. Well, they can be tricky too. I gave you
the URL to the link and you could work on it. Once you're done, I don't want
you to modify the document anymore. I want to send it to our boss. But, how
could I know you didn't keep the URL somewhere in your bookmarks? How do I
know, of all the coworkers I sent the URL to, one of them doesn't keep on
updating that document even when I don't want to anymore? With copies, I'm
safe, do whatever the hell you want with your copy, I don't care anymore. But
a reference to the original document? That can be dangerous.

~~~
SureshG
>That's basically what java and python do. Well, they can be tricky too.

But,you can easily make the classes/collections immutable to avoid the issues
you mentioned. I think in java records and many collections are immutable by
default. Immutability is fundamental to functional style programming.

------
gotoeleven
Sure they're hand crafted but are they artisinal and free range and carbon
neutral?

~~~
philosopher1234
They were baked in a wood fire oven, with the classic Napoleon style.

------
ganstyles
This looks pretty cool. When I was learning Go a long time ago, I used a site
called Gophercises and found it really helped me understand the language
better.

------
efiecho
I have not yet been able to find a simple "Hello World" example of starting a
new project with Go modules instead of $GOPATH.

~~~
triztian
Hey there I found modules to be confusing coming from GOPATH too, but they're
straight forward, super barebones example:

    
    
        #!/bin/bash
    
        cd $HOME
    
        # Create project directory
        mkdir hellogo
    
        cd hellogo
    
        # Init project modfile
        go mod init example.com/hellogo
    
        # Create the main source file
        # Uses bash's heredoc
        cat << EOF > ./main.go
        package main
        import "fmt"
        func main() {
            fmt.Print("Hello world")
        }
        EOF
    
        # Build it
        go build
    
        # Run it
        ./hellogo

~~~
sk0g
You can also skip building, and run directly using `go run`!

------
gotzmann
I've compiled a few interesting quizzes about Go's slices:
[https://medium.com/@gotzmann/so-you-think-you-know-
go-c5164b...](https://medium.com/@gotzmann/so-you-think-you-know-
go-c5164b0d0511)

------
notokay
Why snaps? Is apt-get not good for you already? What's wrong with it?

------
crunchbang123
If you're interested in interactive language learning exercises, then try
codewars([https://www.codewars.com](https://www.codewars.com))

------
mpoteat
I can never tell whether these titles are referring to the programming
language or the board game.

~~~
minkzilla
Neither can I but it’s not much of a problem because I’m interested in both!

~~~
sound1
Good one! BTW, it is 2am here :-)

------
edem
This doesn't ask the most important question: why would I learn Go at all?

~~~
loudlambda
To answer the question: what would a language look like if you put it's
designers in a time capsule for 20+ years and had them make a language that
was uninformed by all the language advances and learnings they'd missed out
on.

~~~
d1str0
This doesn’t answer the question at all. Also it’s very disingenuous. The
designers of Go were very much aware of the the last 20 years of language
development. They decided on a subset that catered to software engineering
between teams of people spanning a length of time.

It purposefully leaves out lots of features and cutting edge design
philosophies because many Of those make things difficult when sharing code
between multiple developers Spread over a long length of time.

Go’s philosophy has always been close to KISS. Don’t provide all these cutting
edge tricks and tips because you can accomplish the same thing in a far
clearer and maintainable way by doing it simpler.

~~~
loudlambda
This is the story I keep being told, but it doesn't seem to match with the
reality of a language. Two example off the top of my head:

Loop variables are captured by "reference", not by value, so it's very easy to
create bugs where you capture accidentally capture the wrong thing and don't
have the value you'd expect.

Nulls, the billion dollar mistake. Most languages are quickly moving away from
nulls (and pointers for that matter), or creating constructs that make them
much safer (such as what typescript is doing). Instead go doubles down on both
of these. In the last decade of programming in kernel level c, python, ruby,
c++, java, typescript, scala I've never worked with code that crashes so much
and is as buggy as go.

Both of these problems could have been addressed fairly easily without
bloating the language. Google has people on the c++ committee; it very much
feels like the creators of go had too much hubris to walk down the hall or
across the campus and kindly ask a good language designer to shoot holes in
their design.

Another example is "iota". How does that make code sharing easy at scale? Any
time I see iota, I have to start manually counting lines, and remember the
rules for if blank lines or comments bump the counter, and it completely
circumvents the ability to quickly grep for a value seen in a log message. It
is completely antithetical to teams of people and spans of time and whatnot.
It seems more like a team of three people who randomly had ideas and ran with
them without thinking the consequences through very well, or consulting the
wisdom of others.

~~~
sacado2
> Nulls, the billion dollar mistake.

That "billion dollar mistakes" is an excellent marketing expression (nobody
wants to make billion-dollar mistakes! We should avoid that null they talk
about! It looks so expensive!) but I don't know how actually true it is. Do we
have any kind of scientific paper that proves languages without null lead to
way less expensive software than languages with null?

I'm not talking about memory unsafe languages like C or C++, but situations
where, in a memory-safe language, a null pointer exception in production
happened to cost a shitload of money.

I'm pretty sure I never had a nil dereferencing in production with my go code.
Invalid array access, off-by-one-errors, yeah, sure, way too many, but very
few languages can prevent them at compile time. But nil dereferencing? I can't
remember that.

~~~
SureshG
Kotlin is one example where it's difficult to make that mistake. Kotlin does
provide nullable type and everything can check at compile time and it so good.
So if write code in pure kotlin (java interop has null issues) you can avoid
null pointer errors. It's really good.

~~~
sacado2
I totally agree it's great and tend to enjoy languages that don't provide the
user with unchecked nulls. It's a cool tool, but I don't think it's worth a
billion dollars. If I had to choose, I'd rather take non-mutability by default
rather than compile-time enforced checking of null pointers.

------
alexandrerond
This is great, but I think it should be written in Rust.

It will then run way faster and be completely bug free.

~~~
zealsham
Their is nothing like a bug free code as a result of the programming language
used . RUST programmers are like the new version of those Haskell programmers
that spams every functional programming thread with a message that tldr:
"write everything in Haskell or die "

