 So let's welcome Shariar with the talk Go For Python Developers. Thank you. Thank you. So we'll talk about Go For Python programmers as a way of introduction. My name is Shariar. I'm a software engineer based in London. I work at OSPR. OSPR is a pretty cool company that we can talk about after the talk if you're interested. Before I start, I think I owe everyone an apology. As I spent more and more time preparing this talk, I realized it's probably not a great idea. And it's not a great idea because it implies that we should use Go as we would use Python, and that results in automatic Go code. It's just not a good idea. And then I thought about it a bit more, and I was still convinced it was a bad idea this morning. But I've done it now. But my intention here is not to write Go code like you write Python or write Python like you write Go. I think it's just as a way to compare the two languages. More or so, I think this is probably more appropriate as a Go conference. Not sure why I brought it to PyCon, but a Euro Python. But, you know, I've spent the time now, and we might as well have a go at it. It's quite interesting, regardless, as long as we know that the intention is not to write Go code like Python, because why would you ever do that? The talk structure is we're going to quickly go over some history, very basic brief history of the two languages, then talk about general syntax and semantics, comparison, and finally, one thing that I think is quite interesting, because Python is very strong at it, is talking about the ecosystems and tools available to developers. To set the expectation, there's expected that you have some knowledge of Python, at least, to be able to make the comparison. No particular knowledge of Go required, and the depth at which we discussed Go is not necessarily something intense. It's going to be very brief, very high level. If anyone's here for a deep diving to, for example, compare and gazing at Go with Go routines, that's probably its own talk, it's not going to be here. But we can start with some history. So, Go... Well, let's start with Python. Python first appeared around 1991, and we know it was influenced a lot by ABC, which was a, by the name, it was meant to be a very simple programming language to learn, etc. A lot of Python's philosophy is from ABC, and a bunch of other stuff, Algol 68, Haskell, Modular 3, etc. Go, on the other hand, is very young. 2009 was around the first time it appeared. But the languages that influenced it still go way back. So there is stuff like Algol 60 and Haskell C, a big influence. But there is also... One of the key things about Go we'll talk about later is the concurrency, and that was influenced by CSV, which is not necessarily a language. I'll talk about that later, we don't have to worry about it now. But we'll see, it goes quite young. It's been quite popular, but Python, obviously, huge history. It's been going on for a while, well, huge. You know, 1991. To start for syntax and semantics, I think the most boring thing to do, which I've done, would be to just do a simple hello world, and go over the basics, and then try to dig a bit deeper. So we can see on your right, the hello world in Python, with the weird caveat that I have an extra weird variable declaration, that's just to show the example for declaration and assignment. And on the left is the go one. The thing about go is every go file has to have a package name, for example. So the first line of every go file is usually a package name. It should be a comment, but then after the first real line of any go file would be a package. And that is pretty explicit. And it's interesting, in Python, packages work a bit differently. You kind of know it from the directory, if the directory is a package in Python 2. But in Go, that is super explicit. You have to have the package declaration at the beginning of each file. And every single file, go file that you put in the same directory has the same package. Again, very explicit. If everything is directory full, every file in that directory will have package through on the top of it. So when you're working with it, you just go right to the top, you know exactly what package you're in. I quite like being explicit. So does every other Python programmer, I guess. But the next thing, typically, like most Python files are import statements. And it is very similar to Python. You import packages. There's no concept of, you know, packages and modules. So you don't say from something, import something else. You generally import the whole package, and then you can use that. If you have multiple packages, you put them on separate lines. It doesn't matter how it works, because it's quite simple. You kind of use a parentheses, and then you just say import once, and you just list everything in a string. It doesn't matter. And then there are also functions, you know, like there would be in any language. We'll talk about this later. The weird thing that I put there, which is a kind of declaration and assignment that is not necessary, was just to go over how that would work. So, for example, text in this case is a string. Now, one thing I did mention, so go is statically typed, which is very different to Python being dynamically typed. And in this case, we haven't really said text is a string, but the compiler can infer that. We'll talk a bit about that later. Speaking of declaration and types, we can do a quick comparison of types in Go and Python. Generally speaking, there are kind of four types in Go, so we have the normal basic types, and we look at them a bit. We look at the list in a bit, which is you have the ints and floats and stuff. You have the aggregate types, like a struct. Again, we'll look at it later. The reference types, like a map. And there is one thing that is an interface type that kind of doesn't exist in Python. And I say kind of because we'll see conceptually Python uses it. And we do have the ABC stuff, but they work a bit differently to how it works in Go. So we'll get to that shortly as well. But as far as the basic data types are concerned, Go gives you a bit more granular types, which is what you would expect because it's statically typed. So you kind of want to be a bit wise with what you choose. So you have many different bits of ints and unsite ints. In Python, they're all just longs. You have, again, different sized floats. We don't really need to care about how many bits there are in Python, although we can if we want to. And then you have complex, boolean string. I guess boolean and string are pretty standard. Complex is useful, too. The ints and uint are, we're not specifying how many bits are in there. That system dependent is usually 32 or 64 bits, but it depends on the system where you're compiling. Nothing we need to worry about for the purpose of this talk. The other category of types were aggregate types. One of them is an array, which an array, arrays are just fixed-length sequences of zero more elements of a particular type. Now, they're not really lists in Python. They're really more Python arrays that you can also use. Because they have to be typed, and we'll show there is a concept, there is something similar to lists in Python as well and go, but they're not arrays. And struct is just the thing used as to contain certain fields inside it. It could be similar to classes. It seems to name topol, which is really a class, but whatever. But it isn't... It's not apples to apples, but you typically use struct where you would probably use a class in Python, or a dict, or that kind of having fields and to create a certain concept. Then we have reference types. Slices are the things that are very similar to lists. Generally speaking, you wouldn't want to work with arrays in Go. You have slices, and slice is a part of an array, and then you can do all sorts of stuff. You can do a list with them. So they're pretty powerful. Maps are basically dicks. They're hash maps. Yeah, very similar. There's also this reference type called the channels in Go that there's no equivalent in Python, really. Channels, we'll talk about later, are the way, are used for concurrency, and for two processes to talk to each other. And they're an actual type. We'll talk again later. Channels are typed. There's also a pointer type I'm not going to talk about, because it doesn't really matter. Well, it matters in Go, but it doesn't matter for the purpose of discussing this comparison. Finally, and I said there is an interface type in Go. Interface is used for generalization applications. So as you would expect for an interface, there's this thing that I want to mention now that we'll talk about later, which is in Go, interfaces are satisfied implicitly. And that is why I think they're very similar to how things work in Python. Again, we'll talk about that later. We can go back to declaration and usage. So there are really three ways you can declare and assign stuff in Go. The first one is you create a variable of type string, then you assign some text to it. Now, at the point where that variable is declared, so var text string, text is an empty string. And one of the things in Go is that when you declare a variable, it automatically takes a zero value of its type. For example, ints would be zero, floats would be 0.0, reference types would be nil. And that is quite interesting because it's meant to be used, and you can have some fun with it. For example, if we wanted to take, I don't know why we do this, but if we want to take random input from a user from the standard input and count the number of times they type something, we could create a map called counts, and that's a map that's going, you know, the key is a string and the value is an int. It will be our count. If we take the input, it doesn't matter how we do it with the new scanner, and then you go through every time someone types something, you read that, and what we can do is we can look at that text as the key into the map, but initially, because it doesn't exist, the default value, the zero value for int is returned because that's the value of the map, and then you can just do a plus-plus on that, and you're good to go. Doing something similar in Python will probably use a counter, this particular behavior results in something similar to default dict, but again, every other type has zero values too, so ints have zero values, floats have zero values, everything has zero values. Functions are very similar to Python. The only thing is because it goes statically typed and kind of declaring your types matter, you give your type, we'll look at an example now, in the parameter list, you also need to have a result list, for example, you might have taken an int and returned a string, or taken an int and returned a tuple of string and float, so you would want to specify that. A crappy example would be to take A and B and add it to each other. If David McIver, author of Hypothesis, I don't know if you guys know it, was here, he would probably stab me because that could break in so many ways, but anyway, so that function will take two ints, we'll return an int and just add to them. One thing you could also do, which is kind of sweet, is that you could name your results, so you could say, in this case, call it C, and then you can straight away assign to it and do stuff with it. Again, in this case, it doesn't make sense because I even forgot to change return C. As you can see, but you can do stuff like that. And you know, just like you could do recursion with functions, like Python, there's no telco optimization, or at least it wasn't last time I checked, the idea being that if your function can be optimized, just try to loop. And a type of a function is a signature, and it's just a sequence of inputs and the sequence of outputs. So the signature for this function, any function that takes two ints and returns one int has the same signature. And that is useful because, like Python, functions are first class citizens in Go as well, so you can pass them around so you can have variables that point to them, so you might want to have a variable that points to a function that takes two ints and returns a string, and that would be the signature of your function. I just said that. The zero value for functions is nil. We don't really care about that, but again, it's this emphasis that things have zero values. And you can return multiple values from a function, like a tuple that you can do in Python. If you don't want one of them, again, the idiom is very similar. You use an underscore as a throwaway name, and you take it. But this is interesting because the ability to return multiple values from a function leads us nicely to how error and error handling is done in Go, which is quite a bit different to Python. In Python, we would typically do a try-accept else finally, and we will catch exceptions and do things with them. In Go, there's no concept of an exception in that sense. What you do is usually the last thing returned by function is an error, and then you check for that. Check to see if it's nil. If it is nil, then you're good. If it's not nil, then you're good. That's incorrect. But you can do the same logic with the errors in Go. Sometimes we want to catch a particular one. For example, the IO package could return and end the file error so you can check. You could say if error equals equals io.eof. So you can do specific ones as well. Now, you might say, well, what do we do finally? How do we make sure something gets run? Go has this concept of defer, and defer is often used where you would use finally or ensure in other languages. And what it does, it says, OK, so create the file. It doesn't matter how that does that. And you defer close file. And what that says is run close file whenever I'm kind of leaving the scope of this function, basically. So you can do that immediately after you open a resource. You can immediately say defer close it later. And it's all in one place, and you won't forget later. We'll probably get back to this in a bit as well again. But it's kind of interesting. Interesting way of dealing with that. There are, however, sometimes where there are genuinely exceptional circumstances. You know, dereferencing a nail pointer or out of bounds in an array. And in those cases, go just panics. And you can also... Panic is actually a function that you can call yourself. You can make your program panic too. And the thing about panic is that the idea is that it will stop the execution of the code where it panicked. It will run all the deferred functions. And it would do them in the last and first out. So if you do like three deferres, it would kind of do the last one first. And then the program crashes with log message if you don't do anything with it. And the idea, as far as I've seen and used and understood, is that you don't really want to stop panics. You don't really want to handle them. If there's been a situation where you go as panicked, then you kind of want to, you know, you're done. But it is sometimes used to recover from it and there's mechanisms to do that. For example, you know, if you have a web server and something bad happens, you don't want to just keep the connection open, you know, forever. You might want to recover from that panic, even maybe send an error back to the client and then maybe you can close everything or maybe you can recover from it. We can take a quick example. For example, in a parser, sometimes, you know, even if everything's appears to work fine, the complexity of a job is in a way where bugs may still look in. And generally speaking, what you can do is don't, in those cases, you don't necessarily want to panic. So there's this concept of recover. So what you do right to the top of your function, you defer a function. Because we said when in Go you panic, all the deferred functions get called. So when this deferred function gets called after a panic, recover will return that panic if there was a panic. And if there was a case, then you could deal with it and either die or try and control it and carry on with your program. So in this case, in the case of a parser, you can just write the error and carry on or, you know, whatever. I took this example directly from the Go book. And recover will return nil if there has been no panic. So it's not really a problem. You also shouldn't... I'm not going to talk about panics anymore. They exist. Running out of time. So what about object-oriented programming? Python is pretty object-oriented. Everything's an object. Go is also apparently considered object-oriented, though Go's definition of it is a bit... So Go says an object is simply a variable that has methods and a method is a function associated with a particular type. So you could... Yes, you have that. And I'll go through how you can use it in a sec. There is no inheritance. I don't particularly enjoy inheritance, usually. So composition is the way to do things. And let... You know, we can go through it quick again. Pointless example. Pointless. Because it's point. I didn't even realize that. So in Python, you would define a class. You know, a point has x and y coordinates, at least in 2D space. In Go, you would do the same with the struct. So you define this type point. It has an x and a y that are float 64s. Those are called fields, so we have an x field and a y field. And we all know how to add methods in Python. You just add another def under there. It takes self, and then it does some stuff. For example, if you want to take the distance between two points. Well, in Go, you kind of attach a function onto that type. And you could do this to basically any type, any user-defined type. So although the... It looks a bit different. It's not in the same scope. You know, that's how it works. That's how you end up having methods. And both of those, you know, calculate the distance between two lines in the different languages. But as I mentioned earlier, there are no... There's no inheritance in Go. But the way Go kind of handles that, the circumstances where you wouldn't need inheritance is by struct embedding. And when I first read this few months ago, it said it composes types by struct embedding. And I thought, what, by what, what it... It was a bit of a mouthful. But when we take an example, it would be pretty sweet. Imagine we had the point class, now we had a named point class. And the point of it is that it hasn't... I keep on saying points when talking about points. Hmm. So we have a point class and a named point class and a named point class also has a name for a particular point. In Python, to do that, you would probably create a new named point class, subclass point, and just add a new instance variable to it. In Go, what you can do, we already had our point struct. We create a named point struct, and you can embed point inside it. And what does that mean, is that when you create named points, you already have access to x and you already have access to y. So you just... I can show you here. So named points, you know, you pass it that point and you can access named point on x as if x was part of named point. Because it is, it's embedded inside it. And you can, you know, call the functions and everything as well. So that's the way... I don't want to say inheritance is handled, but that's the way you do embedding for those kind of circumstances. And obviously, there is one more OOP-esque thing in Go as well, which are interfaces. Conceptually, they're actually very similar to duck typing in Python. You know, if you have dunder len, then something that needs dunder len just knows how to deal with it. You don't really have to do much, or dunder equal or whatever. It's really the same in Go. And the way, earlier I mentioned that they're satisfied implicitly, that's what I meant. You don't really have to do anything. As long as a struct, for example, has all the methods that an interface expects it to have, then it confirms that it satisfies that interface. And an example, kind of from the actual built-in IOP package, is like writers and readers and readwriters. So, you know, a writer interface, as long as something has a write method that takes some bytes and returns it into an error, then that satisfies that interface. And you can also mix up interfaces like that. So, readWriter kind of takes writer and reader. For example, OS that stood out conforms to some of those. It also conforms to the satisfied closed interface. Similar in some ways to ABCs in Python as well, although I actually think it's just the way duck typing is. I'm just trying to think. I have one minute left. Let's see what happens. Go, one of its main strengths is concurrency. And that's kind of what everyone bangs on about. Python also has concurrency. Concurrency in Go is mainly done in two ways, either go routines, which is the thing that is quite famous, or traditional shared memory. We're not going to talk about that because that's not really interesting. So, in terms of sequential processes, I mentioned CSP earlier on. It's something Tony Hoare was working on in 1970s. And it isn't really a programming language. CSP is more of a formal language for defining how concurrent things interact. And the thing that I don't know if it came from Go or whether it was there before, but people who do Go often say do not communicate by sharing memory by communicating. So the whole idea is that you don't really share memory, but you have these things we talk about called channels that talk to each other. Go routines are just lightweight threads managed by Go Runtime and they're pretty sweet to run. You just prepend Go to a function and that's run in a separate Go routine. To show you a quick example because I have to hurry up. That's literally how it works. You say go waste time and it does that in the background and it carries on. So it prints end of main first, then it will print time wasted because that thing delayed for 2000 milliseconds. I don't know why anyone would do that, but still. And then there's the concept of channels and channels are the way you communicate between two Go routines. By the way, you always have one Go routine which is the main Go routine that's when you start the program. Another basic example of a channel you created channels are like pipes in Unix for example but they're typed. You can't just put anything in it. You type it. So we create the channel of type int, then we have an anonymous function which is a bit like anything else you could do that. You can't do it in Python, but I guess you have lambdas but they don't really work anyway. You can write to a channel and that function writes 42 to a channel and both writes and receiving from a channel are blocking operations. And then over there we can read from that channel. So basically we print 42 which is amazing. I'll do this bit in 30 seconds. I wish I had more time but the ecosystem and tools in Python I think are pretty solid. The same goes for but Go comes with a lot of built-in stuff. For example, for testing there's in your terminal you type in GoTest and there's certain conventions that if you follow you can just test all your GoCode. Unit test is pretty good, PyTest is pretty sweet in Python. They're all really mature stuff. With Go anything that ends with underscore test are test files. Any method that starts with test is a test method, any method that starts with benchmark is a benchmark test method and something that's pretty interesting is any method that starts with example is an example function that provides machine check documentation. So that's pretty interesting too. So really there is one way to do these things that Go defines and it works pretty sweetly. For Go formatting or code formatting, not Go formatting you just, again, use the terminal Go format your source and just format it. If you install this as a plug-in to an ID every time you save it does that, every Go file looks the same. I sometimes find we use Flake 8 for our Python development and it doesn't necessarily do where to put a line break if your line is too long or that kind of stuff. Well it does but you might not agree with it. So that doesn't really happen because Go just does it. There's one way to do it and Go will take care of it. Again, for package management there's quite a few different ways to do it in Python, you can pip install has at least been the most common in my lifetime. Go has a concept, again from the terminal, comes with it, Go get package and it just gets it, builds it. Another thing about package management VirtualM is pretty well used in Python to manage different versions and pair project requirements. You use Go path environment variable when working with Go. It's, it could be annoying but if you end up having a nice way of dealing with it then it's fine too. I quite like virtual learning the way it works. That was fast. Finally Go comes with document generation and you just do Go. There are quite a few tools again that do that for Python but I don't think it's in the standard way that Go does it. It's one way of doing it and it just does it well and everything looks the same. So those are kind of the ecosystems and tools and I guess the conclusion is that none of us can work with Go programmers and I'm not saying we should all move to Go or all stay with Python but the idea was just to get a feel for what's there in Go and that's it. I don't think that nothing, nothing too concrete just get a feel for Go and I know a lot of people have been moving to it whatever if that's what you want to do. Anyway, that's it. Thank you. Unfortunately we don't have any more time for the question and answers but you can chase him and ask him personally and now enjoy the coffee break.