

Learn X in Y minutes where X = Go - realrocker
http://learnxinyminutes.com/docs/go/

======
buro9
This is the way I like to learn a language.

Instantly, and progressively, by starting at the top and working through a
single document that is both a reference and a guide.

Beautiful work.

Edit: One change I would make is to change p := pair{3, 4} into p := pair{x:
3, y: 4} which helps your declarations keep working in the future when you
extend or modify the definition of `pair`.

~~~
mseebach
> when you extend or modify the definition of `pair`.

Well, pair is an anti-pattern anyway, but what _exactly_ would you add to
"Pair"? "File not found"? :)

[http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx](http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx)

~~~
acuozzo
> Well, pair is an anti-pattern anyway

So _cons_ is an "anti-pattern" as well, then?

Your comment is the most original dis of Lisp I've ever read. Bravo!

~~~
mseebach
Go isn't a Lisp, last I checked. I am referring to "Pair" as a class/interface
in an OO language. If you're using Pair to construct a linked list in a OO
language, I salute you, but that's even more of an anti-pattern.

Pair is an OO anti-pattern because it's an arbitrary grouping of two things in
a generic container, and you shouldn't do that in OO - classes are cheap. You
should make a class that represents what the collection of those two things
actually are. Typical field names in generic Pair objects are 'left' and
'right' or 'first' and 'second' which tells you nothing about the values you
stick into them (except the types, if you're using a strongly typed language).
If, as suggested in the example, the pair holds a 'x' and a 'y', a better
choice could be to call it "Point" or even "Point2D". If it's a key/value pair
from a map data structure it should be "Entry" with fields "key" and "value"
\- etc.

~~~
jerf
It is worth pointing out that the pair in question is indeed an {x, y int}
(using Go's ability to elide repeated types, so this means both x and y are an
int). The name may be poor, but since it also will in general use be paired
with the module name, it may not be, either. "Pair" is a poor name,
rationals.Pair might not be.

A truly generic Pair in go would be Pair{interface {}, interface{}}, and that
would be a code smell. (Only a smell though, since it's possibly part of some
larger construct that is basically getting around Go's compile-time type
system and replacing it with a run-time check.)

~~~
mseebach
It's generic, not in the Java-generics sense of the work, but in the sense
that x and y are generic names - they don't tell you what x and y are. Yes,
they are of type int, but are they apples or oranges? In the example, they are
indeed just two numbers that we chose to keep together, although the name and
field names suggest that the author has a point in mind.

rationals.Pair is still a poor name, it's a pair of what and for what purpose?
Assuming you're referring to rational numbers, ratio struct {p, q int} is
better.

~~~
dllthomas
In my C code I've been moving away from distinguishing primitive types by name
alone, preferring to wrap them in single-element structs to get some type
safety:

    
    
        do_things_with_fruits(apple_count_t apples, orange_count_t oranges);
    

instead of

    
    
        do_things_with_fruits(int apples, int oranges);
    

Which saves my ass when I wind up writing

    
    
        do_things_with_fruit(basket.oranges, basket.apples);
    
    

Note that at that point, I would say a generic pair type (not allowed in C but
borrowing C++ syntax)

    
    
        pair<apple_count_t, orange_count_t>
    

is really no less informative than something like

    
    
        fruit_basket_t
    

and if it's easily defined (tuples + inference?) I see no reason to avoid it.

~~~
mseebach
Yes, it's less informative, because you're missing the context of why the
apples and oranges are lumped together in the pair. FWIW fruit_basket_t is
poorly named too, since fruit baskets not things that can count apples and
oranges (and nothing else), they are generic containers capable of holding all
kinds of fruit.

I like the single-element structs. I've been finding myself doing that more
and more in Java and I quite enjoy it. First epiphany was replacing bool with
enums.

~~~
dllthomas
I don't think "fruit_basket" (or "fruit_counts", say, addressing your later
point) really gives much more clue as to why you're grouping these things than
does the templated pair. When there _is_ an informative name, use it, to be
sure. Occasionally there's not much more reason than "I am using both of these
elsewhere. This is much more the case when things are used locally than when
they are exposed in interfaces, to be sure.

------
gutsy
MULTIPLE return values?! My mind is BLOWN. That's awesome. My work is all in
Java and there are so many times on my last project where that would have been
helpful (I know I can do it by creating a map or an array or something, but
that's stupid and extra code that I shouldn't need to write).

I really hope to be able to write Go professionally at some point, it is a
really nice language to write in.

~~~
dllthomas
If that blows your mind, check out Haskell - you can _dispatch on type of
return value_.

~~~
th0114nd
Care to elaborate?

~~~
dllthomas
As an easy to follow (though questionably idiomatic) example, consider the
typeclass Default:

    
    
        class Default a where
            def :: a
    

and an unwise pair of instances:

    
    
        instance Default Int where
            def = 7
    
        instance Default String where
            def = "foo"
    

This means I can say:

    
    
        3 + def + length ("c" ++ def)
    

and get back 14. Note that _which "def" depends on the type expected where it
is used_.

\---

It's not limited to values, either. Consider the "return" function in the
Monad typeclass:

    
    
        return :: Monad m => a -> m a
    

which is a function that takes something and returns that something wrapped in
a monad. Which monad? Whatever is expected at the call site.

    
    
        [1, 2, 3] ++ return 4
    

gives us [1, 2, 3, 4] because list is a monad and return for lists gives a
single element list, whereas

    
    
        putStrLn "foo" >> return 4
    

gives us an IO action that, when executed, prints "foo" and yeilds a 4.

\---

A super complex example is variadic functions like printf, with the type

    
    
        printf :: PrintfType r => String -> r
    

PrintfType can be a String or IO (), giving you something like C's sprintf or
printf based on the call site (which is itself cool), but it can also be a
function that takes an instance of PrintfArg and gives back some new
PrintfType (in an interesting intersection with currying).

------
pjungwir
Wow, I'm not really interested in learning Go, but I was drawn in and made it
all the way to learnInterfaces. Congrats!

One question: why have named return values (in learnMemory) if you return
something different? If you didn't have a return statement at all, would the
function return the final value of p and q?

~~~
jdiez17
>why have named return values (in learnMemory) if you return something
different?

Probably to avoid declaring the function as `func learnMemory() ( _int,_
int)`.

>If you didn't have a return statement at all, would the function return the
final value of p and q?

No, you have to do that explicitly. You can do `return`, though, which will
return the variables whose names match the definition.

------
chollida1
This looks very similar to the "easter egg" that the F# team put into visual
studio.

When you create a new F# project you can select F# Tutorial and it generates a
working project with a source code file that is an introduction to the
language and its features.

I wish more IDEs did this.

------
thenonameguy
My hungarian translation of it: [http://learnxinyminutes.com/docs/hu-
hu/go/](http://learnxinyminutes.com/docs/hu-hu/go/)

------
cliveowen
I'm tired of reading that this or that language/framework is "easy-to-
understand" and "fun" to use. That's a subjective statement and mostly not
true. Writing code is a means to an end, you want the output of a program not
a bunch of lines, so I don't see how it could be fun (which is repeated over
and over again in the official documentation and various slides and talks).
And the concept of easy-to-understand is determined by the level of experience
of an individual plus a whole lot of factors that are beyond us, not least of
which is the sheer brain power.

~~~
enneff
What we mean: All of us on the team have a lot of fun writing Go. We often
show each other little pieces of code that delight us. This seems to happen
more when we work in Go than in the other languages we use (or have used), and
so we attribute the fun-ness to Go. Pretty straightforward. I'm sorry you're
so tired of it.

~~~
cliveowen
Wow, I didn't expect to get a response from an actual Googler, working on Go
no less. Anyhow, I also remember when people were saying that Java was a fun
language to work with, but I still have to find a single engineer who doesn't
think of it as slightly more than a pain in the ass. It's all a matter of
right-sizing expectations; using and objective language keeps you from being
called out should those expectations fail to be matched.

That said, I've already professed my love for the Go language, which I
consider the spiritual successor of the C programming language.

~~~
aeden
Java _was_ fun to play with back in the early days. It was fast, had a VM,
garbage collection and was OO. Sadly the fun was gradually removed over the
years as a result of design-by-committee and a desire to try to solve some of
its core issues.

Fortunately you can still have fun on the JVM, even though I prefer to avoid
it these days given its current custodians.

------
dan00
Is the documentation of go regarding the 'map' data type and the usage of the
function 'make' out of date?

Because I can't see any difference in:

    
    
        package main
        
        import (
            "fmt"
        )
        
        func main() {
           m1 := map[string]int{}
           m1["a"] = 1
           fmt.Printf("%d\n", m1["a"])
        
           m2 := make(map[string]int)
           m2["b"] = 2
           fmt.Printf("%d\n", m2["b"])
        }

~~~
jerf
Compare with:

    
    
        func main() {
            var m1 map[string]int
            m1["a"] = 1
            fmt.Printf("%d\n", m1["a"])
        }
    

[http://play.golang.org/p/JJQ7dSZLeA](http://play.golang.org/p/JJQ7dSZLeA)

which yields

    
    
        panic: runtime error: assignment to entry in nil map

~~~
dan00
Well, but this again works:

    
    
        type pair struct {
            x, y int
        }
        
        func main() {
           var p pair
           fmt.Printf("%d\n", p.x)
           fmt.Printf("%d\n", p.y)
        }
    

That's just wrong, that declaration and initialization behaves differently
depending on the type.

~~~
jerf
If I could unilaterally make just one change to Go, I'd adopt C#-style
nullable types, and change everything to be nonnullable without the extra
sigil (or whatever, I have no passion about the syntax itself, just the
feature). This would produce, say, map[string]string vs. map?[string]string.
The first would not be permitted to be null, the second would.

It would be my choice because unlike a lot of other pet ideas which would
radically change Go into a new language, I'm pretty sure this would have
hardly any effect... excepting of course to remove the Billion Dollar Mistake
from the next up-and-coming language.

~~~
dan00
Well, I'm more or less a programming language nerd and these kind of things
just hurt =).

Just try to pass a 'map' or a 'struct' to an other function. The 'map' behaves
like passed by reference and the 'struct' behaves like passed by value. If you
want to pass a 'struct' by reference than you have to use a pointer to a
'struct'.

Seriously? What kind of ad hoc programming language design is this?

------
emehrkay
Where exactly does the struct pair implement the Stringer interface? Is it
when the String method was added to it? What if you have interfaces with
similar names?

~~~
thisishugo
>Is it when the String method was added to it?

Yes, that is how you satisfy an interface in Go.

>What if you have interfaces with similar names?

The problem of interfaces with similar names is actually no different than the
problems of, for example, packages or functions having similar names. It's
down to you to avoid naming things in a confusing manner.

------
reyan
This is great. I suggest adding fallthrough statement in one of the switch
cases.

------
cldr
> It’s not the latest trend in computer science

Uh, I think it is. I can't go three articles without seeing Go mentioned.

I'm going to get downmodded to gray, but either this tutorial is missing
something or Go is _way_ over-hyped. I saw nothing special in the language at
all, I have no idea what all the obsession is about lately.

------
ovi256
Thanks! Inspired by you, just wrote the Romanian translation for Python. Maybe
I'll do Go next :)

Seriously thinking about writing the Django equivalent of Michael Hartl's
tutorial for Rails. Intimidating as it's a lot of work, over 100k words. Any
people would like this? I really could not find a Django/Python equivalent.

~~~
jamesjporter
That would be awesome, I've found the existing Django tutorial rather wanting.

------
cliveowen
This is very well useful and very well done, may I suggest to keep things
consistent and actually use the syntax /* */ for multi-line comments?

EDIT: Also "// x == 1 here." should be "// x == 2 here.", those are 3
iterations.

~~~
mseepgood
> I suggest to keep things consistent and actually use the syntax /* */ for
> multi-line comments

Idiomatic Go code almost never uses multi-line comments, see:
[http://golang.org/src/pkg/net/http/request.go](http://golang.org/src/pkg/net/http/request.go)

> Also "// x == 1 here." should be "// x == 2 here."

No, it's correct. := declares a new variable. The newly declared, inner x
shadows the outer x only within the block scope of the for loop:

[http://play.golang.org/p/cP2dWyg0qw](http://play.golang.org/p/cP2dWyg0qw)

~~~
cliveowen
Yeah, right, I didn't see the external variable. I might as well go ahead and
delete the comment :P

------
munchor
Really great way of learning the overall concepts of Go, but that code should
have been gofmt'd!

------
Tloewald
I thought the comment "x == 1 here" could use a little more explanation (I
figured it out, though, so maybe not.) I also found the function signatures
confusing, especially the function with a local variable q that is nothing to
do with its returned value q -- seems like a bit of a wart in Go. (Being able
to assign return values vs. using return, as in Pascal, seems like an obvious
reason to declare return values this way. Perhaps this feature exists but is
not explained.)

------
NKCSS
I think one of the string format examples missing the type formatter:

fmt.Println("it's a", i)

Should be something like:

fmt.Println("it's a %T", i)

See [http://golang.org/pkg/fmt/](http://golang.org/pkg/fmt/) for more options.

[update]

Forgot they allowed to send pull requests; done :)

~~~
enneff
Println does not take format strings. You're thinking of Printf.

~~~
NKCSS
Yup, forgot to edit that :-/

------
enneff
I really love this format. Such a nice document.

------
gtani
I've been reading Chisnall's Phrasebook and Summerfield's Programming in Go
books. Both are well done as far as descriptions of language features and
standard lib go (covering 1.0), but are a little short on extended code
examples.

And the usual amazon pricing: new $26, used $35.

------
cwills
Does it bother anyone else that Go supports the GOTO statement? I would've
thought GOTO an obvious construct to leave out when creating a new language,
to protect programmers from themselves? (See Dijkstra on 'GOTO statement
considered harmful')

------
kunil

        // If statements require brace brackets, and do not require parens.
    

Even if it is single line?

~~~
kilburn
Yes, but you shouldn't ever see single-line _if_ s in go, because _gofmt_
forces all of them to be multi-line.

This is one of the strong points of go (whether you like it or hate it):
_gofmt_ imposes the same formatting rules for everyone using the language.
It's not a choice for you (or your project) to make. Period.

~~~
omaranto
It's easy enough to never run gofmt, so there is still a choice. :) In fact,
not running gofmt requires less effort than running it.

~~~
melvinmt
Not if you install the (excellent) GoSublime plugin in Sublime, it will run
gofmt on every save.

~~~
omaranto
Learning to use some newfangled editor and figuring out how to install plugins
for it when the editor you've always used works just fine sounds like much
more work than running gofmt. :)

------
antimatter
Loved this. Can someone point to a relatively simple open source project
written in Go that I can dig into to learn further?

------
mrcwinn
Hm, would it not be where x := Go?

------
prezjordan
It's killing me that no one has made an APL version yet!

------
defly
Need for Clojure.

~~~
Posibyte
I believe they have one:
[http://learnxinyminutes.com/docs/clojure/](http://learnxinyminutes.com/docs/clojure/)

