
Stages of learning Go, with code examples - beliu
https://sourcegraph.com/blog/live/gopherconindia/112025389257
======
bonn1
Just wondering, does Go finally has a package manager with proper versioning
of modules?

 _Edit: Somebody is heavily downvoting me on every reply, I would love to know
why. I like Go and want to get into it since a few months but the missing
package manager held me off. So what is wrong about my question?_

~~~
NateDad
You really don't need a package manager for Go. Honestly, the main reason you
need them for node, python, etc is because you're deploying source code to
your production environment. You don't do that with Go. You deploy a binary,
which has everything wrapped up in itself. Think of it as a self-contained
virtualenv that requires zero effort on your part :)

In Go, code is packaged via source control repos. If you want a different
version, you need a different repo. There are some tools to mitigate this, so
that you can get away with a different branch per version (see
[http://gopkg.in](http://gopkg.in)), which can make it a little nicer for the
maintainer to deal with multiple branches. To the consumer, it still looks
like a different repo (i.e. every different version is a different URL to a
repo).

Note that because Go is a compiled language, the only time versioning comes
into play is a _development time_. As long as your developers are using the
right version, you never have to worry about versions during deployment.

Now, if you're concerned that your project depends on code repos from external
sources, then there are several tools that can insulate you from third parties
doing stupid stuff. The most complete and best one is called godep, which
basically has two modes - reliable and paranoid. The reliable mode insulates
you from changes made to a repo you depend on by recording the exact VCS
revision your project is using and always checks out that commit. That way, if
an upstream repo checks in a breaking change, it won't affect you (and you
control when you update to newer commits in that repo). Paranoid mode actually
copies all the code from your dependencies into your own repo. This insulates
you from upstream repos getting deleted. And of course, this gives you the
ability to test out upstream changes before integrating them into your
project. The tool makes it easy to copy all of your dependencies at once with
a single command, so it's not a huge hassle to do (which it would be if you
had to do it by hand).

~~~
apunic
> You really don't need a package manager for Go. Honestly, the main reason
> [...] is because you're deploying source code to your production environment

Not sure if I would agree with that. A full-fledged package manager automates
the process of installing, upgrading, configuring and removing software
packages in a consistent manner. Dependency management and semantic versioning
is an important part to provide this consistency. Wether you deploy source
code or binaries does not make any difference why a package manager is always
good to have.

~~~
pjc50
We really don't need any more _binary_ package managers - that should be the
responsibility of the platform you're deploying on. dpkg/rpm/etc on Linux
systems, MSI on Windows, APK on Android, etc.

~~~
pjmlp
One reason I love package managers, is that as developer I don't want to
produce a dpkg/rpm/tgz/apk/msi/ipa/p5i/depot multiplied by the different
locations of include files, libraries, documentation across the said OS.

Specially in commercial software.

------
coldtea
Where does this idiotic idea cames from that being "idiomatic" is some kind of
virtue?

Idiomatic Java was the FactoryProxySingleton EE-wank fest from Apache, SUN,
Spring and co.

It was by changing those idioms around (e.g. how the Play framework wrote
Java), that saner alternatives emerged.

The de-facto idiom of PHP before 2010 was messy code.

It started getting more coherent after that, but the preffered idiom now (e.g.
for Zend, Synmphony, Laravel) is still a tedious, verbose, copy of the Java
circa 2006 style (large class hierarchies, singletons, "Facades", DI, etc).

Idiomatic JS pre-Cockford was ad-hoc BS. After Cockford it got a lot better,
but then it changed again (can't say for the worse) with all sort of
functional tricks and patterns that weren't in vogue before.

In all of those cases, if they have stuck to the same "idiomatic" way from the
start, it would have been worse.

Within a single project, sure, enforce some idiomatic way of doing things.

But within a whole language people should be able to experiment and not be
called upon for being "unidiomatic" all the time. This is exceptially
disturbing and often in Go, where there's some cargo cult in many advocates
that they have found the be-all end-all way to code.

It seems to me this push for "idiomatic" is also related to the Blub paradox.
Blub programmers know a couple of ways of doing things (the "idioms" of their
language) and cannot understand why someone might want to program with higher
(or just different but convenient) concepts he learned in another language.

~~~
disputin
The lower the standard of your team, the more you will appreciate idiomatic
code. I don't work in SV, blue chips, or anywhere that could use Scala. A
couple of us at my last place had a hard time moving the team from Source Safe
to SVN, Git was out of the question. "What's the point of commit messages if
you only commit every three months?" \- not kidding, not a junior. Lines
thousands of characters long, literally. I saw a pattern once. Once. CIO was
one of these copy/paste VB devs, common in London, an unfair generalisation,
but necessary as a warning sign. Some people become developers without any
interest in development, completely oblivious to *nix/open source world,
simply as a job, 9 - 5, and might have flipped a coin between development and
accountancy. Some places don't give a shit about software development, or the
idea of engineering - "just get it done!". Resharper, fxcop? Yeah, right.
Degrees don't all teach compiler design, some just Java OO and a bit of
Glassfish. If Go replaced C# in all of these arbitrary SMEs there would be far
fewer WTFs. But people would struggle without Visual Studio debugging and a
big run button. I'm being harsh, and seriously, not suggesting anything about
MS devs, who include the world's best as well as the world's worst, but I find
people on this site are often, to their fortune, oblivious to what working in
the 99% can be like (the figurative 99%). Long live idioms, gofmt, golint.

~~~
waps
Are you making the argument that Go is finally the magic language that can
make bad devs write good code ?

Let me be the realist here : it isn't.

Go is just a very young language that, for the moment, only has developers
that are curious and therefore either good or willing to learn. This has the
additional consequence that for the moment the mailinglist is very helpful.
History teaches us that both effects have nothing to do with the language and
are temporary (unless the language never sees any "real" acceptance, like
Haskell).

You can look messages from some years back showing the same sentiment for
Delphi, Visual Basic, Java, Python (especially Python had lots of people
making this argument), ... And when those messages were posted, they were
true. It didn't last long for any of them.

> But people would struggle without Visual Studio debugging and a big run
> button.

Sadly this is being used as an excuse for making language with substandard (to
put it mildly) debugging facilities and editors.

And of course, like for every other argument, the Go team itself is just being
extremely arrogant about this. "Why do you want this ?" type responses, or
just dead silence, or outright declaring the people asking the question to be
substandard developers or some such.

------
DanWaterworth
> Phase 4 (the expert): You understand the design choices and motivations
> behind the language. You grok the philosophy of simplicity and
> composability.

In what way is Go code composable?

~~~
1_player
You probably were sarcastic, but in case you are not there's a brilliant
article from Rob Pike about using and composing functions to create flexible
APIs: [http://commandcenter.blogspot.co.uk/2014/01/self-
referential...](http://commandcenter.blogspot.co.uk/2014/01/self-referential-
functions-and-design.html)

There is countless proof about Go's composability through functions and
interface, but I keep coming back to that one document.

~~~
moe
_There is countless proof about Go 's composability through functions and
interface_

I can't tell if you're serious or sarcastic yourself. The article proposes
this snippet, presumably copy/pasted for every option:

    
    
      // Verbosity sets Foo's verbosity level to v.
      func Verbosity(v int) option {
          return func(f *Foo) option {
              previous := f.verbosity
              f.verbosity = v
              return Verbosity(previous)
          }
      }
    
    

If that's what Go composability looks like then...uh... No thanks.

~~~
cjslep
> presumably copy/pasted for every option

To be fair, there is "go generate" now that can generate functions that would
otherwise require tedious copy/pasting. If you are familiar with the
preprocessor in C++ expanding template definitions, this tool can provide
similar functionality but is more generalized.

I think embedding [0] is the real big composability win in Go.

[0]
[https://golang.org/doc/effective_go.html#embedding](https://golang.org/doc/effective_go.html#embedding)

~~~
copsarebastards
> To be fair, there is "go generate" now that can generate functions that
> would otherwise require tedious copy/pasting. If you are familiar with the
> preprocessor in C++ expanding template definitions, this tool can provide
> similar functionality but is more generalized.

Comparing to C++ templates is a rather generous comparison. C++ templates
provide a rich type system that allows type checking and prevents errors, and
integrates with the rest of C++'s type system.

Go generate is a lot closer to C/C++ macros, the only improvement being that
the generation is done in a turing-complete language instead of by text
substitution.

In C-like languages this problem is typically solved with generics, but the go
team has decided to ignore 20+ years of language development and try the same
thing that didn't work so many times that it motivated the creation of
generics.

"But," you say, "Generics slow down compilation!" To which I respond that the
first step to compiling code is creating code that does something worth
compiling.

~~~
cjslep
I agree, it is a generous comparison, which is why I only compared "go
generate" to expanding template definitions (albeit, in hindsight, even that
is generous). Macro expansion is definitely a better comparison. In no way did
I mean to insinuate "go generate" is on par or better than C++ templating
language features.

Edited for clarity.

------
Animats
It's a tool, not a religion. Don't try to turn it into a cult.

~~~
campoy
As the speaker I couldn't agree more, actually check slide 39
[https://speakerdeck.com/campoy/gophercon-india-evolution-
of-...](https://speakerdeck.com/campoy/gophercon-india-evolution-of-a-
gopher?slide=39)

------
politician
What do GOPATH, the project folder structure, package management, and package
versioning all have in common? The go command. Not the linker, not the
compiler -- the `make` replacement.

If you want to fix the most broken parts of Go -- its ecosystem management
tooling -- just replace your `go` command.

I have, and I love working on a project with a proper top-level src folder,
with vendor-able packages discoverable in a top-level lib folder pinned to
known-good commits.

There are literally dozens of go replacements, but the winning combination for
me is using Goop [1], Makefiles, and symlinks to subvert `go get` and the
naive way it parses import declarations [2].

[1] [https://github.com/nitrous-io/goop](https://github.com/nitrous-io/goop)

[2]
[https://golang.org/ref/spec#Import_declarations](https://golang.org/ref/spec#Import_declarations)

~~~
NateDad
You don't have to replace the go command to do that. The only thing that needs
the GOPATH and expects import paths to be URLs is "go get". You can very
easily make a go project that uses all relative import paths and put it
anywhere you like. Dependencies then just get copied into whatever path you
like using whatever name you like.

However, your code will be unusable by anyone who follows the normal Go way of
coding, so you'll be missing out on working with the rest of the community. If
you're writing proprietary software, that might not matter too much. But if
you're writing open source code, it will be a huge hindrance to getting
contributions from outsiders.

~~~
politician
> However, your code will be unusable by anyone who follows the normal Go way
> of coding.

Well, that's not really true given the major projects using tools like Godeps
[1], so while that argument certainly sounds good, it doesn't actually seem to
be a problem in practice.

[1] [https://coreos.com/blog/godep-for-end-user-go-
projects/](https://coreos.com/blog/godep-for-end-user-go-projects/)

~~~
NateDad
Actually, CoreOS is using the version of godep that rewrites import paths, so
that most developers _can_ use "go get". The only time you need to use godep
is when you're updating one of the vendored dependencies. That's actually the
awesome thing about godep - it keeps your repo go-getable.

> the simplicity it presents to regular contributors and users used to _go
> get_ make it worth the additional effort

------
copsarebastards
> _Don’t wait until you become an expert in the language to make your voice
> heard._

You can do anything!

[https://www.youtube.com/watch?v=gSjLiQxEZlM](https://www.youtube.com/watch?v=gSjLiQxEZlM)

------
kylequest
"If you think the Go standard library is not powerful enough to do what you
want to do, you might be wrong."

or not...

The standard libraries are not perfect. They do have very useful building
blocks, but they are far from complete or perfect.

Take the http library, for example. There's no built-in context:

type HandlerFunc func(ResponseWriter, _Request)

type Handler interface { ServeHTTP(ResponseWriter, _Request) }

This resulted in a complete mess when it comes to http middleware because
everybody is solving the context problem their own way (including google
itself).

------
tgeery
If they just made the page wider, I might be able to read their code samples
with minimal effort...

------
runeb
Can someone recommend some good books on Go?

~~~
kingmanaz
Summerfield's "Programming in Go" is several years old but still the best I've
come across. Below is a review regurgitated from Barnes and Noble if you're
interested:

...The author spends his time away from the libraries, covering the core of
the language. By the nature of this approach the matter is dense, but it also
gives the author ample time to discuss best practices, for instance:

"...[i]ncidentally it is a Go convention that functions that have channel
parameters have the destination channels first, followed by the source
channels [in the function definition]..."

Many of these best practices stem from conventions found in Go's own source
code, which happily, the author is well acquainted with. Learning a language
by isolating its syntax and analysing idioms and conventions is effective for
those willing to persevere, and "Programming in Go" abounds in such detail.

Ideally, "Programming in Go" should be paired with a textbook which focuses on
use-cases. Balbaert's "The Way to Go" is such a book, but sadly, is not nearly
so well written as Summerfield's. In any case, "Programming in Go" is the book
for those searching for a solid understanding of Go's fundamentals.

