 Okay, so as you might tell from the opening slide, this is a repeat of a talk I gave at PyCon Canada a few weeks ago in Toronto, except this is the fast version. So the origin of this, why I am standing in front of a room full of Python people talking about Go, which is a completely separate unrelated programming language, is because about a year ago I had this crazy project I wanted to implement, a new build tool which needed to be reasonably fast and more importantly I didn't want it to be tied to any particular high level language, even one that I like as much as Python, because I have this crazy idea that we shouldn't have one build tool per language, we should have one build tool. So I was shopping around for, and I mean I know C, like a lot of people who are over the age of 35, and C is a really painful language for writing anything large. So shopping around, you know, I knew that there had been a lot of interesting work in statically compiled languages over the last couple of years. I knew about D, I knew about Go, I knew about, I just learned about Rust while I was in the process of this, and I checked them all out. So I really liked D and I really liked Go, and a year ago I really didn't like Rust, and at the end of 20 minutes I hope to explain to you why I used Go for this project. So in a nutshell, Go is a statically typed language, like Java or C++ or Haskell, but with type inference. It's natively compiled so there's no byte code, it just goes straight to x86 machine code or ARM machine code, statically linked, which is pretty cool, no runtime dependencies, you just generate one big, fat binary and you're ready to deploy. It is object-oriented, but not as we know it, Jim. It's garbage collected, thank goodness. It is concurrent. Instead of threads and mutexes, there's a much better abstraction for concurrency in Go and it works very nicely. Go is aggressively minimalist. If you've started using Python like before 2.2, you might think you know what a minimalist programming language is like, but you don't know minimalist until you've used Go. They really take it seriously. It is brought to you by the brain trust behind C and Unix. These guys know what they're doing. I'm talking about Ken Thompson, Rob Pike, and well, those are the main two and some other people at Google. And Go is an excellent alternative to C. Before I dive into the real content here, some links, you'll notice those bottom three, this is like HTML presentation, so you'd have to click on them. You can get those slides from the URL on my website, which is down at the bottom on every slide, so you can follow along home quite easily. Here's an example. Here's a very quick introduction to the type system in Go. Variables are declared, and one way of doing it is declaring that A is an integer and B is an N32. That's explicit typing or explicit declaration with typing. Or you can do it implicitly with using type inference, and that's how I've declared C here, that colon equals is an alternate assignment operator that says, hey, compiler, you figure out the type of C for me based on the other side of the expression. The assignment, the attempt to define D is an example of just how strict Go is. Even on a 32-bit machine, Int and Int32 are different types. There's no automatic coercion, and that's a lesson learned from many painful experiences with C, which has very complicated rules for promoting numeric types that nobody except Ken Thompson really understands. So there's been a big trend, I would say, okay, a big trend, Go and Python, moving away from automatic type coercion. Go explicitly discards the heritage of C, and the same thing happened in Python 3, where the automatic type coercion of string types is gone. In Python 2, a rich source of bugs is automatic implicit accidental unexpected coercion from byte strings to unit code strings. In Python 3, that's no longer allowed, and it must be done explicitly because we learned from our mistakes. So there's a bunch of built-in types, pretty familiar, not very surprising if you've used C99. Oh, wow, there's a built-in string type, big, big advantage over C, not really surprising if you've used any programming language other than C in the last 30 years. There's a bunch of other built-in types, which are more interesting, like arrays and slices. Slices are... Implementation is somewhat different from Python lists. The interface is quite different, but it's the same basic idea. What you'd use a list for in Python, you would use a slice for in Go. There's maps built in, just like Python dictionaries. Structs are just like C structs, essentially, so the closest thing in Python would be a named tuple. There's pointers, nice, fun. Function types, done right. Functions are first-class objects, and a function that takes an int is not the same as a function that takes a float, it just works. Closures are excellent, everything just works out of the box. And then the interesting novel stuff are interfaces, which are kind of like Java interfaces and kind of like ABCs in Python, abstract-based classes. They're like Java in that they're static enforced by the compiler. They're like Python in that you just implement an interface, you don't have to tell anybody that you've implemented it. And then the really cool one is channels, which is half of the concurrency story in Go. So one of the interesting things about Go is that it's object-oriented, but not as you know it. So the three key ideas behind Go's approach to object orientation is, one, you can attach methods to any user-defined type. Two, composition. Every object-oriented language you know today probably is based on reuse through inheritance. There is no inheritance in Go. Instead, composition or delegation is a first-class citizen in the language, and you get syntactic shortcuts for composing objects rather than inheriting classes. Three, interfaces, the big one. So here's an example of methods. I have defined a user type. This is probably something anybody, lots of programmers have done. It's got a UID and a first name and last name. By the way, anybody who writes code like this to, whoops, whoa, what just happened, to model actual real-life human names, every time you do that, shape-shifting reptilians eat a kitten. That's not enough to generate, to represent human names, but I'm simplifying. So my user type has a method full name. Ta-da, not very interesting. But what is kind of interesting is the syntax. I don't know any other languages that work like this. Instead of having self or being self like in Python or implicit and automatic like in C++ and Java, you explicitly declare that this method is a method, or this function is a method of the user type, and this is the receiver object. The convention, instead of calling itself, is to just say you or user. But that's a convention just like self is in Python. But I think the rest of this is fairly obvious, right? It doesn't take any arguments, it returns a string. Now here's something more interesting. This is something that static typing people just love, the idea that you can define a UID type to prevent you doing the horrible accident of multiplying a UID by a GID or a file size. I think those of us who have embraced dynamic typing just say, whatever, don't do that. But there's a lot of programmers who really salivated the idea of having a compiler enforce this. And what's cool about Go is there's basically no cost to it. You define a type UID as Uint32 and it is a 32-bit unsigned integer. End of story, it takes 32 bits, that's it, that's all. Any operations you do on that UID are machine code 32-bit unsigned integer operations. They're fast. What's really cool is that you can add a method on that. If I told you, as a Python programmer, to define a UID class to contain a single integer so that we can have a next method, you'd laugh me out of the room for the grotesque inefficiency of that. In Go, there's no penalty. It's 32 bits. So more interesting is composition. So here's the hard way, the traditional way of doing composition that you may have done in Python or Java or C++. So I've got a user type which has a UID and it also has some privileges. And I put privilege set in a different type, just, you know, it seemed like a good idea at the time. So, but I want the methods of privilege set to be visible to user, right? I just want to, if I've got a user object, I should be able to call hasPrivilege setPrivilege without knowing about this implementation detail. I want it to be part of the interface. So the way I do it is I reimplement hasPrivilege as a delegate, a wrapper around privilege. And the same thing here. Boring. What's cool about Go is you can get that behavior for free by embedding a privilege set in your user type. So the only difference between the declarations of the two type, here, the privilege set in user two is explicitly named. Here it doesn't have a name. It's anonymous. And poof like magic, that's called embedding. That's a language feature that takes the methods of this guy and makes them methods of this guy. So it's a lot like inheritance, but it's not. I mean, it fills the same niche in the language that inheritance fills in Python or Java, but it's not inheritance. And then finally, interfaces. So, so far this probably, if you're familiar with Java, this looks like a Java interface. The particular spelling is different, but it's a type that has some methods in it. And the methods have arguments and types and return types. So, okay, how is this different from Java? Oh, I guess I don't have another slide on that. The way that it's different from Java is that you don't ever declare I implement privilege set. You just have these two methods and boom, you're a privilege set, like magic. And that's the same idea as abstract based classes in recent versions of Python. Which is pretty cool. So the control flow in go, not too many surprises, but it's a good example of the aggressive minimalism. There's no while. So there's if, and there's for, and there's switch, much like C. There's no while loop. And there's no do while loop because you don't need them. You can do it all with a for loop. So why mess up the language with unnecessary features? Functions are just done exactly right. They're real closures, everything works beautifully. First interesting or another interesting example of both aggressive minimalism. And something you wouldn't expect in a modern language is no exceptions in go. Which is a real surprise because every language in the last 20 years has had exceptions. And the workaround in go is you have multiple return values. You need to return your regular thing and you also return an error object. The other thing that exceptions are nice for is try finally. Well, there's a nice little mechanism for that called defer. And the way defer works, you just do file equals and you open a file. And then the next line of code is defer file.close. And it doesn't happen right there. It's deferred until the appropriate point, which works very nicely. And there's also a panic mechanism for genuinely exceptional conditions. If you run out of memory or a dereference and Neil Pointer, you get a panic. You don't panic on failure to open a file because that is not an exceptional condition. Files are unreadable all day, every day. It just happens. It's not exceptional. That's the go attitude. I like exceptions personally, but hey. So here's an example of error handling in go. It's a classic example. You're writing a million bytes to a file and halfway through the disk fills up. What do you do? You've got partial success and partial failure. Well, the answer is you return the number of bytes read 506,000 or whatever, and you also return an error object. So the good news is that go accurately represents what really happened writing this file to disk. The bad news is you got a lot of tricky cases to handle here. So I think the rationale for why go does error handling this way, I mean the case against exceptions, number one, exceptions mess with control flow. If you're reading through the code, you're looking at line I and then line I plus one in a language with exceptions, you don't know that line I plus one will follow the execution of I plus one will follow the execution of line I. There might be an exception in go. That's not the case. It will happen. And then the other really good reason is how do exceptions mix with go routines and channels is an open question. This is easily goes most controversial design decision. I don't like it. I like exceptions myself. But I understand where they're coming from. So concurrency. This is just about the simplest example of concurrency I could come up with. It's all based around channels and go routines. And if you think go routine sounds like co routine, that might not be a coincidence. So here's the idea. Responder. So the idea, what I'm doing here is I'm going to have two go routines. They're a lot like threads or processes, but they're not exactly. That's why they have a different name. And one of them, the one in the main go routine is just going to send ping, ping, ping, ping, ping to the background guy and the one in the background is going to send ping, ping, ping, ping back. Not very interesting. But the way it works is so there's another go routine was just an ordinary function called responder takes a channel and the two go routines communicate over this channel. So there's a dedicated operator, this little arrow, which means send some data over the channel. And it also means read some data over the channel, read some data. So this is it. So this is a channel. And this is a value coming off that channel, which I assigned to a local variable so I can print it. So the background go routine is just an infinite, they're both infinite loops, right? Remember, I said there's no while, there's no while true or while one, it's just for that means infinite loop. So the background go routine just takes a data off of the channel, prints it. And if it's the expected value ping, send back pong, otherwise send back pong. So that's concurrency and go in a nutshell. So when I say go is aggressively minimalist, I've given a couple examples already. Here's another one. Of course, go has a testing package in the standard library. Nobody would take you seriously if you invent a programming language in 2007 or 2009 or whatever it is and don't include a unit testing package. But what's interesting about that unit testing package is it doesn't include any assert methods. You go look at Pi unit in 2.7. And there are dozens of assert methods because you might want to assert that these two values are equal or they're almost equal or they're equal except for order that this really raises an exception, blah, blah, blah, blah, blah, blah. It's even worse in J unit because there's integers equal strings equal arrays equal blah, blah, blah, blah, blah, blah, blah. They just said, why should we do that? Go has perfectly good methods for comparing objects. Use them. And there's a perfectly good if statement. And if these two objects aren't equal or whatever your test is, you are perfectly capable of calling the fail function yourself. You're a grown up, you're a programmer, you do it, you don't need our help. The other rationale they give is that you should spend the time to write good failure messages, rather than using the testing library as a crutch. And you should structure your tests differently. Instead of having a long sequence of very repetitive similar assert this, assert this, assert this, assert this, assert this, you should loop over a list of expected and input values and expected values. They call it table based testing, which is a useful technique. Personally, I prefer unit testing in Python than in Go, just because it's less typing. But it's a good example of their aggressively minimalist stance. Why have this fluff in the language? Why have this fluff in the library if you don't really need it? So my personal experience, I've after doing, I don't know, five or six months, about 10,000 lines of code in Go, it is definitely not as fun, easy and productive as Python. For I think some of the reasons I've explained, and there are various other reasons that just get in your way. Things that get in your way. For performance, Go blows Python out of the water. There's no question. It's directly compiled the machine code when you add two integers, that's all you're doing. You're adding two integers. Go is much nicer than C. And I'm speaking as somebody who likes C. If you'd asked me a year ago, I would be no question about it that C was my second favorite programming language. I do not like C++ or Java. And I'm not surprised that Go is a lot nicer than them. After putting in my time with Go, I honestly can't decide if C or Go is now my second favorite language. Or D is pretty cool too. I played around enough with that to get a good impression. Anyway, oh yeah, yeah. So big win. Concurrency built in. It's a massive win over pretty much any, I mean, Java is the only other mainstream language that has built in concurrency features, and threads and mutexes are a pain in the neck, people. Go routines and channels are much, much nicer. I miss exceptions. That's a big downside of Go. I understand. I accept that it's difficult to get exceptions and concurrency working. I don't care. I got them working. They're a great language feature. If you're designing a language and you have to choose between tuples and multiple return values, choose tuples. It's a more general solution. The idea of having your programming language and your compiler enforce a particular coding style, big win. I think Python started the trend 20 years ago and Go is dialing it up to 11. I'm not so keen on the particular style they chose, but hey, that's okay. That's it.