 Ah, excellent. I assume that you can all hear me because I can hear me just fine. Okay, is there anything special I need to do to make it start recording? Yes, no, maybe. We'll go with maybe. This talk has been recorded before in a very similar incarnation and I have specially designed these slides to stand alone because I'm about to dump more information on you than I would expect any reasonable person to remember in an hour. So, I hope you're all here to learn a bit about rust without any assumptions about where you're coming from. So, we're gonna have a quick intro, talk about running rust, writing rust, and then improving rust. So, this is an intro class. I'm going to cover what to expect from rust, when to pick it, and when not to pick it, and then how to get going with it. This is not gonna be hack time. It's not gonna be any particularly unsafe or advanced rust. Those are like special topics, 200 level, go hassle a compiler author to give you a talk. And I'm not gonna have time for a particularly exhaustive Q&A, but at the end of each section, I'll stop and take questions on that content. So, when I have a question slide, please pipe up with anything I may have lost you on at that point. So, it's just the basics and what questions you should be asking as you go on. I am the DevOps engineer from Azilla Research, which means that my day job is actually mostly Python. I keep the infrastructure that tests and builds rust and servo going. I'm on the Rust community team because I have this habit of going out and evangelizing and talking about it. I come from a background of lots of open source software and a bit of embedded development in robotics, not like building the compiler. So, if you have particularly advanced questions on that side of things, I will have to defer to someone who actually knows the correct answer. And from the audience here, we've got a pretty full room. Congratulations for showing up this early on a Sunday at the End of the Conference. I'm really glad that you're all here. Who here has heard of Rust? Show of hands. Cool, excellent. I don't see anyone with their hands down. You're about to hear more about it if you were shy or lying. So, who here has used Rust for anything or tried to? So, a few people, maybe a quarter of the room, that's totally awesome. I've got the right people in the room here if you're not using it extensively yet. And has anybody here contributed to Rust? So, nobody? Cool. Welcome, it's gonna be a fun journey into the language. So, who here has worked with a lower level language, C, C++, Assembly, Fortran? Just about all the room, that's excellent. You will already be convinced when I say things like managing memory is hard. And if you never have, then feel free to kind of poke one of your neighbors who raised their hand and go, is it really that difficult? And they'll be like, nope. Who here has written a scripting language, higher level language, Java, Python, Ruby, JavaScript? Again, practically everybody. See a few people without their hands up. Anybody here written in a more academic language with a really nice type system on it? So, a few people, maybe a quarter to half the room. Cool. So, there might be one or two of you for whom this is your first introduction to programming. If so, this may move a bit fast for you, but I hope you'll be able to pick up some of the key concepts there. So, just to make sure we're all on the same page, use version control. Yeah, most of you, all of you, used GitHub in particular. Cool. Rust's community tends to be very GitHub centric, so you'll get used to that model as we go through. And you've mostly worked on free and open source software at some point, right? So, yeah, if you're familiar with community contribution models, then many of Rust's decisions will make a lot more sense. So, Rust is a systems programming language. That means that it's supposed to run right on the metal, it's supposed to optimize for speed, and yet, it's supposed to remain safe. And that's where Rust stands out compared to other systems languages. Rust is also an overarching community of a bunch of people who think that it's important to be not jerks to each other while writing code. And, of course, there's a handful of people who disagree with this allegation. Up next in the slot, you'll hear a talk about Go. While Go is a fantastic language for a certain set of problems, it is not really a direct competitor to Rust in the way that some people think, because Go is a language for sysadmins. It is a language for being easy to learn from C and yet an improvement, whereas Rust kind of steps further out there and says, we are willing to tolerate quite a steep learning curve in order to get these fantastic outcomes at the end. So, we're about safety, speed, and concurrency. You can get memory safety in Rust without having to have garbage collection pauses because of the checks that are done at compile time and the rules that are enforced that we'll talk about. We focus on zero cost abstractions and the real slogan is that you should be able to hack without fear. So, who here knows what garbage collection is? Might have struggled with it. Again, just about everyone. Basically, your computer only has so many little boxes to put things that it remembers in. And once it's done with a particular little box, it has to reuse it later, otherwise your program would run out of memory as you need to allocate more and more things. So, different languages have different approaches to figuring out how to only let parts of the program that should be allowed into those little boxes get to them and not forget anything while they'll still need it. C says, here's the rules. You're smart because you're writing C. Just follow the rules universally throughout your program, you'll be fine. This is sorta okay for toy programs. It's good to know the rules for learning it, but when your program starts getting really large, it becomes harder and harder to apply a rule throughout the entirety of your program and hold it all in your head. JavaScript, garbage collected languages say, um, yeah, that's really difficult. I'm not gonna ask you to do that. Just wait a minute while your program's running. I'll go sort things out and come back and resume running. This has obvious performance implications when you're running on smaller, especially embedded hardware. And Rust's approach to garbage collection or avoiding it is proving that the program can't do something wrong while it's running as you compile it. This does give you a slower compile time, but it gives you a fast and safe program that's at the end of it. Quick history on Rust. Project started in about 2010. It's been stable for about two years now. We're, oops, I didn't update that slide. I'm originally, I think, 116 at the moment. And Mozilla employs most of the core developers, although Rust is explicitly a community project. If, for some reason, Mozilla were to say, no, Rust is not a thing we want to pay people for anymore, there is no reason that the language couldn't keep on going. And some projects you may have heard of that are implemented in Rust include the Servo browser engine, Habitat, the infrastructure tooling that the chef guys have written, Dropbox uses it internally to speed up some of the tasks, and you can see a bunch more projects that use Rust at the friends of Rust page. So when should you use Rust? Basically, if you've hit the wall on some other language and you say, oh man, I should consider FFIing out to C to speed up this hot code, say I should consider implementing that hot code in Rust instead. If you're doing a new project where speed and safety are essential and you want to play with a cool new tool and don't mind spending a while getting up to speed on it, Rust is fantastic. If you're on an architecture that LLVM can target, it will be pretty straightforward to use Rust on your device. If LLVM doesn't support your architecture yet, then you will have quite a bit of work to do getting that support in place before Rust will be able to use it because some of Rust's speed comes from the decades of work that's been done on LLVM. And if you're working on a team that likes embracing new things, using Rust can practically be a reward of here's this cool shiny tool you get for being awesome. Now, when shouldn't you use Rust? If you need your thing done in a hurry and you know how to do it fast in a language that you already know and you don't know Rust yet, might not be the best time to pick it up. If you need to reuse a lot of code with very close coupling to a library that's implemented in another language, you might want to consider using the language of that library, although Rust has a variety of foreign function interface tools available to you, including a tool called Corode, including BindGen and other things that you can find which one meets your needs as you identify those needs. Or if for some reason you're not in a group that's willing to abide by the code of conduct that says basically don't be jerks, be constructive with your criticism, or we don't want to work with you, then you're probably going to have a frustrating time engaging with the Rust community if you don't want to work the way we do. So any quick questions about when and where to use Rust? Yes, right there. Yeah, how low can you go? How small a device can you run Rust on? As you get onto like 8-bit architectures, it's, there's not as much work that's been done on Rust, so you may find some bugs, find oops, we needed a new compiler test there, and you won't have the standard library available to you if you're running without an operating system. However, you can still get the safety and performance benefits of Rust, so you'll just be pioneering a bit more than you would if you were running on let's say 64-bit Linux. Memory footprint, generally you can, I don't know the exact specs of that, but you can work to carve it down to fit on just about anything. If you find a problem there and you're like that code should be smaller in C, file an issue on the compiler, and an author will get back to you on here's why that is, here's why we can or can't get it smaller. So yeah. Can you run Rust bare metal on x86? Yep, without the standard library, you'd probably be interested in looking at the Redox operating system that's being implemented in Rust. They have slightly forked the compiler because there were a few different priorities that they wanted to have versus the main compiler, but it is by and large still Rust and they plan to reunify when that's feasible. And then the second part of your question was how's IO, can you poke around in memory? Basically you will want the MEO crate, the missing IO libraries. Most of the wrappers around IO to abstract it are implemented in other crates and you can pick the right one for your particular use case based on your needs rather than having that come from the standard library. Question back there. What was the intended target hardware or OS for Rust? So that has kind of a two-part answer. First off, Rust's overarching like grand plan is wouldn't that be fantastic if we had something that was just as good as C, but safer and better in all the ways? And more specifically when Graydon initially invented Rust it was because he was frustrated by trying to use C++ to develop a browser engine and he was like wow it's too easy to shoot myself in the foot. So for platforms running like I would say Linux x86 is kind of the original thing that was tested the most on at the outset but Rust should be able to target anything that LLVM can. So let's see, yeah one more. So is it still the case that Mozilla would want Firefox in the list of multiple projects? Basically Firefox ships Rust because they've ported components from Servo into Gecko to speed up and improve bits of Gecko. So yes, if you're running Firefox, if you're running a latest Firefox you're executing a little bit of Rust code, correct. So to move on since we're pretty constrained on time let's talk about what kinds of Rust are there, which one do you want and how do you get it? Basically Rust comes into three channels. There's nightly where we try out crazy new ideas and they may or may not get into a shape where we can get them into stable. There's beta, which are basically the release candidates and then there's stable Rust, which we have promised will always be backwards compatible. You can read the blog post that came out when Rust 1.0 was released for details on that but we go out of our way to test every release candidate with against the old stable to make sure it doesn't change the behavior of Rust code. So which channel should you use? You should default when you're starting a brand new project in Rust, try to write it in stable because you can set a stable Rust project down, come back to it a year or two later. It should basically still compile with the new stable compiler. Sometimes you'll pull in a dependency that wants a feature that's only available in nightly and at that point you can switch to nightly. In general, all stable code should run just fine on a nightly, maybe sometimes it won't because of a nightly bug but then you wait a day, use the next nightly and you should be fine. And yeah, the moral there is stable if you can, nightly once you hit the wall, nightly once you need a feature that's unavailable in stable. So I mentioned that we test all of, we test new candidates to make sure they won't break code that worked in the old stable and the way we do that is with a very cool tool that Brian Anderson wrote called Crater. What Crater does is using both the old stable and the release candidate, it compiles all of the public libraries or crates that have been published for Rust and it compares the outputs. So if a warning used to be there and went away, warning didn't used to be there and showed up, same with errors, then we know to manually look at it and either fix the candidate compiler or if it was an intentional change, go submit a pull request to the crate that has the problem that was accidentally exploiting a bug in the old stable to help them fix it. So questions about what channel do I use? Just questions about what channel do I use before I move on to how you get your Rust installed? Nope, excellent, I must have explained that clearly. So there are several different options for running some Rust code and the absolute easiest way of running some Rust code is to hop into an online playpen. It'll just execute code for you. If you want to use several versions, like you're working on one thing that's stable, one thing that's nightly and one thing that's on an old nightly for some reason, use Rustup.rs. Rustup will allow you to pick an arbitrary channel and have several installed simultaneously. You can get a Rust from your system package manager, although as of right now, there are few guarantees about whether the stable that you install will be up to date and I don't believe that nightly is officially packaged for any distro at this point. If you are particularly security conscious and you want to know everything about how your Rust was built or if you want to build it with special flags for whatever reason, you're always welcome to compile it from source. Just Rustlang, Rust on GitHub and the instructions are in the readme. So the playpins where you can execute Rust code online, they're open source, you can edit the source if you want to. You could spin up your own playpen if you wanted to. They give you several different options and for if you want to look at the intermediate representation or the assembly that's being run or what have you, there's a just button if you want to share what you've done with an IRC channel and the main difference between Play.Integer32.com and Play.Restlang.org is that the Integer32 playpen allows you to use some of the most popular crates whereas the official Rustlang playpen doesn't let you pull in libraries. So if you're using Rustup, just read the docs in Rustup.rs. Rustup will, by default, put all of its stuff, all of the different channels that you've installed in .cargo bin in your home dirt although that is configurable and then to get Rust once you've got Rustup, you just say Rustup install whatever, nightly, stable, beta. And to make a new project with it which we'll talk about later, you ask it to run nightly with whatever channel and then whatever command you wanted to run if for a new project that would be cargo new. A few notes on the security of Rust distribution. All of the releases are GPG signed. The key is on Keybase.io. We never let any website see the private key. Don't worry, we signed the artifact for Keybase locally but Keybase is a convenient way to verify who's key it is. Rustup will do all that signature checking for you and you're welcome to read the Rustup script and see exactly how it's trying to maintain your security before just executing it. And on GitHub, you can just pull the source and compile it yourself if you're concerned. So when you're actually deploying a piece of Rust code, you ought to check the readme for some system dependencies because every once in a while something will pull in a library that assumes you have some package or another installed, especially as you start working with various operating system utilities. So you clone your project, CD into your project and just ask it to cargo run. That might be multi-Rustup run cargo run if you're using a Rustup run stable cargo run, Rustup run, nightly cargo run, whatever, if you're using the Rustup route. And cargo will handle everything else from there. It'll go get the dependencies or use a cached version if that's available. It'll compile all the stuff and then the file it will run by default is source main.rs. So questions about installing Rust and running Rust code? Nope, cool. So now we have about 40 minutes to talk about writing Rust code, which I assume is probably the part that you're here for. So this won't be a complete synopsis of the book because the book is a very good resource that stands alone, but I'll cover some of the basic things that you'll run into as you start trying to look at Rust and go, what the heck am I even looking at here? So the first thing to note when we talk about writing code is what are you writing it in? We're working on IDE support and it's in various places for various IDEs. So check out where your favorite editor is at. Excuse me. And my IDE, we really do mean editors. There's quite a bit of Vim and Emacs support as well. And then a recent development that's really exciting is the Rust language server that Jonathan Turner's been working on and it allows any editor to hook into intermediate compilation, recompile bits of the code and quickly get the results so that it can use, so that you can get errors and stuff directly in your file that you're editing. So that's pretty good right now and in the process of getting better. So a common question is, do we have a Rust repel, the re-devaluate print loop, like if you just invoke Python on the command line? And since it's a compiled language, that's kind of an odd question to be asking. The best equivalent is generally to use the playpin. Also, if you hop into the poundRest IRC channel on irc.mazilla.org, there's a little robot called Playbot there and if you just have a single line that you want to see executed or you're trying to explain a concept to someone, you can tell Playbot to execute the code and it will drop the result of whatever you asked it for into the IRC channel pretty seamlessly. So there was briefly an initiative to make an actual repel which worked on an old nightly so if you're particularly interested in having that available, that would be a starting point for working on it further. Four life choices. So before you, or as you get into Rust, at first it will tell you no really frequently because you are probably in the habit of writing code that is in some way unsafe or not provably safe and it will be frustrating at first before you get used to it. Just remember, Rust wants your program to be good. So Rust enforces rules that will prove that your program's good and if it can't prove that, it'll say no. If you want to say no, I'm smarter than you or this is IO, you shouldn't be able to prove it, you can override some of those safety guards using unsafe. I won't talk much about unsafe here because before you're particularly confident in what you're writing, it can be very tempting to say, I have no idea how to make that safe so I'll just make it unsafe and that is an anti-pattern. You should figure out how to write your Rust safely, ask for advice if you can't figure it out and use unsafe only as a last resort. The errors deserve and mostly have helpful docs and if you run into an error that comes with some documentation and that documentation misleads you or is actively unhelpful, please file an issue on it because the Rust teams want you to have as seamless an experience and as easy an experience with Rust as you can and if you're using the Playpin, just click on the error number when you get an error and it will take you directly to the docs on that and generally have some suggestions about what you should do. So if you think that Rust is giving you an error when it shouldn't, well, first off, statistically Rust is probably right and you're probably wrong if you're brand new. However, there will be times when Rust is wrong. To figure out what state you're in there, first, search for that error, somebody else has probably blogged or posted on Stack Overflow or generally complained about it. Drop the minimum viable reproduction of the error into a gist and ask around on IRC or on the forums, users.rustslag.org and then if you still think that it's wrong and no one can explain to you how to fix it, file a bug and on that bug you may get a solution for how to fix it or you may get, yeah, that really was wrong. So there are a variety of other useful tools available to you as you start writing Rust. Rust format will turn your code from whatever strangely formatted thing it might be into a standardized, standardized all your indentation, standardized what line your brackets are on and generally make it easy to read. And Clippy will, just like old Microsoft Clippy, suggest improvements. I would like to think that Rust Clippy is substantially more useful than Microsoft Clippy. Any questions about the ideas or the errors that you will be running into? Yes. So with the formatting, is there like a PEP 8 standard? The formatting that Rust format enforces by default is just kind of the generally agreed community best practices which are documented in Rust format itself. You can configure Rust format to make a different decision like if you wanted two space indents instead of four or something like that for a particular project. So there is a default, but it's not as rigidly encouraged as a Python standard would be. So jumping into syntax, the first thing to always look for when you're looking at Rust code is scopes. A scope is just a pair of matched curly braces and everything in between it shares a scope. So they can be nested. You can have an outer one and an inner one. So everything in the outer scope will be available in the inner scope. Things from the inner scope, once that scope ends, will no longer be available in the outer scope. And once that outer scope ends, nothing that was available in either will be available to you anymore. So when a value goes out of scope, it goes away, is no longer available to you. This seems somewhat intuitive, but then there are cases in other languages where you can use a value that would be out of scope and if you try to do that, Rust will not allow it. So your function syntax. You say function, give it a name, and then give it a scope that does something. So the thing that's probably most different from C is that you're going to have to spell out the types of everything your function takes in and everything it's going to give back again. And think of those type signatures basically as madlibs. You're going to have the name of an argument and then the type of that argument, the name of the next argument and the type of the next and so forth in those parentheses. Then you're going to draw an arrow with a dash and a greater than sign and then you're going to tell it the type that you promise you'll give back out of at the end of that function scope. So you don't have to yield a result. You don't have to take arguments in. But if you promise you'll take an argument, you cannot call a function without giving it that argument. If you promise you'll give a result, it's against the rules for it to be possible for the function to exit giving anything but that result. So if you have one branch that like, you think you're never going to go down but that branch wouldn't yield the result, that's not going to compile. So I'll touch on macro syntax here because print line is a macro and we will be printing stuff frequently in the example code. So macros are basically just a condensed function that can take several arguments instead of having a function since a function takes a specific number of arguments. So the syntax there is the macro name bang and then whatever arguments you're handing it, however many you want. You can check in the book for more and that's because we'll be looking at print line. So here's a function. The function have is going to take one argument named x of type 32 bit integer. 32 bit integer is one of the primitives that you have available and it promises it will yield another 32 bit integer. It'll return half of it and then when you call it, you're actually going to be calling it from print line because in your main function, which will run by default, you'll call print line that curly braces are where you interpolate the first value that you've passed it after that in the string and then you're gonna print the result of having four. So that'll print out two. Pretty straightforward. Note that you couldn't use that x after half scope is over. You couldn't use anything that you declared in main up in that function unless you passed it inexplicitly. So four rust syntax just like C or C++ punctuation matters a lot. Any expression will end with a semicolon. There's one little exception to this for sugar for returning a value, which is if you don't say return or the semicolon at the end, you just put an expression as the last line in the function that result of that expression will be returned as the value. I note that more so that you won't go, wait, shouldn't that be a syntax error the first time you see it in code than because of any use of it today? So you care about spaces because they separate tokens. Beyond separating tokens, spaces are irrelevant. You can write your rust in a terrible, horrible way and have it compile and be perfectly happy. And this is why we have rust format to fix it. Sorry about that, especially sorry if you're from Python. So simple rust control flow is gonna be pretty familiar if you've programmed in pretty much any other language. You have conditionals, you have loops, you have while loops, you have ranges that you can iterate over. Some of the neater things are, you have match statements available, which you won't have in every language, which are basically like switch cases. You can check out the exact docs on control flow if you're not familiar with these concepts in the book. So matching is a particularly fun piece of control flow that you won't necessarily have available elsewhere where you can have a variable and then match on that. And in this case, we're going to say, we're matching on day, so if day is exactly two, and then that, they call it a rocket ship in some language equals greater than, it says what we'll do if that condition matched. What we'll do if day was two, second of March, we'll print, it was open in for day. And then all of your things in a match will be separated by commas. You can say first or sixth, and then you can say anywhere between three and five inclusive, or at the end of a match, you'll always want to catch something else, anything else. And that's what the underscore represents. So if nothing else there matched, it'll print that default when it falls through. So questions about the basic concepts of scope and syntax and so forth. Yeah. What does the let do? The let declares a variable. Let says, we're gonna have a variable named day and we're going to assign it the value of five. By default, it will be immutable. That means we can't change it. I'll talk about mutability coming up because I actually will have time because we're doing well on time right now. Other questions about basic syntax here? So I don't have to declare the type of day. That's correct. Rust is smart enough to figure out that day is an integer. And if I needed to pass day to a function or I needed to do a function that only takes a certain type with day, Rust would try to make it of that type. And if it couldn't or I asked it to be two conflicting types, it'd be like, what are you doing? Please tell me explicitly what you wanted there. So if it guesses it's a 32-bit and then you try a 64-bit operation on it, what would it do? Well, if you need to do 64-bit operations on it, I believe it would just, at compile time, go, oh, that looks like a 64-bit to me. If you're doing complex operations that only work on one type of number, you should probably be explicitly specifying its type, not so much for the compiler as for your own reference so that you don't try to do something wrong, yeah? Yes, I could have explicitly said that five was a 32-bit integer. I could have explicitly told it for five to be a float if I wanted to. I just didn't to keep a little bit of extra syntax out. Can you have branches that overlap in the match? I believe that it does the first branch first, or the first hit first, so overlapping is sort of pointless and unclear. So moving on from that, you notice that we're talking about the types of things pretty frequently, but what if you want to talk about several different types? For that, you have traits. And fundamentally, all of these things are just telling you something about the type that has that type or trait. You need to know the type of a value because you need to know how much memory it's going to take up at compile time so that you can plan out your memory usage in advance. And the other benefit is that there to remind you what you planned on doing with a given value and what should and shouldn't be possible with it. So there are a variety of types built in like the 32-bit int that I've been using before, and you can find the whole list of them in the book. So you've got those primitives that you can find in the book. You've also got array types, string types, tuples, other convenient types, and you can construct your own as well with enums. So you can construct your custom types with both structs and enums. You can put pretty much whatever you want in them, and then you can implement traits for them. Like if you think that your custom type should be possible to add to things, you can tell it exactly how to add itself to something by implementing a trait. And when you depend on a library, you can use a type from it. So a trait is kind of like a meta type. They describe what a type can do, so a bunch of types can have the same trait and you implement traits for your type, and they basically generalize input and output. So rather than saying here's my addition function, it only takes 32-bit integers, you can say here's my addition function. It only takes types which implement the add trait, so things you can add. So questions about types and traits? Or shall we get on into some examples? I'll see how we're doing on time. Yeah, we're doing good. Yes. Yeah, you've found situations where you want to typecast from time to time. You could certainly write a function that takes one type, returns another, and then performs the appropriate logic that you wanted for converting between those two types. I don't know off the top of my head whether the standard library does any typecasting. I believe that it does not, because there's a lot of ambiguity about what did you actually want to have happen when you converted an empty string to an int or a string of letters to an int, and so it's generally better to be explicit about that. So something that we touched on as well in that first example, again, it's very hard to look at code and explain the code without all of these basic concepts at once, is ownership. So when I create the value, the name myint, and assign it the value 42, that 42, wherever it sits in memory, is owned by myint. Myint is the binding. It owns the value, and every value has exactly one owner at a time. 42 is actually a bit special here, because it's an integer. If you try to give it away, it'll just be copied because it takes up so little memory, but for most types, all values are owned. So sometimes you'll want to change what's in a given value, and you need to plan ahead if you're going to want to change it, and you need to tell it when you create that binding that it's going to be mutable. And to do that, you say, let mute or myint equals 42. So that means myint will be able to have a different value put into it whenever you want. So before we look at the next example, I'll just tell you in a bit more detail about these copy type things because when you try to break the ownership system using primitive types like integers, you'll find that it doesn't break when it should. That's because the compiler's really smart and goes, oh, that owned it, and you want that to have it as well. Ah, that's so cheap to copy, I'll just copy it and make a new 42 and put it in there. And so to avoid that, we're gonna use a box type that wraps the integer, and so you can access it just like an integer, but it will be allocated differently so that it won't just automatically be copied and you'll actually have to change ownership and you can't keep on using it after you've given it away. So almost all of the types you'll work with are not copy and that's why we are wrapping our special little integer in a box type, yeah? So list manipulation, yeah. In other languages, just to repeat the question, you'll create a list and then you'll reference part of the list and it'll be a pointer into it. You can do that with slices by borrowing a slice of the list and that is probably a useless answer until I explain what the word borrowing means in this context, which is on the next slide or the one after that. So before we can borrow a value, let's look at giving it away. So because again, every value has one owner at a time. So we'll make a main function. We'll create that first value, the first binding and we'll give it 42 in a box. That's just so that we won't automatically copy the 42. That's cool. So then we can print out whatever was in first. It's smart about unwrapping the box and so it'll print 42. And then we'll create second and we will give it what was in first. So now first doesn't own that box of 42 anymore. Second owns it instead. So you can say, hey, second show me what you've got and second will say, I've got 42 because it owns it now. But if you were to try to ask first what it has, it'll be like, I don't own anything. It went away. Stop, please give me a value so that I can print it. And you'll get an error that will explain to you what to do. You'll click the little number in the error and it will say, you gave that value away. Try not giving the value away. Yeah. Is that a compile time error or runtime error? Excellent question. That is a compile time error. Yes. Correct. If you like give first 42 in a box and then when we assigned second we could give second a new box that also has 42 in it. That's fine. That's totally cool because that one 42, that first 42 is owned by first, the other 42 is owned by second. Now, when you compile that code, there would only be one 42 on the stack because those are both immutable so you know their contents is never gonna change and they would actually both be referencing probably the same address in memory because you're certain that you can't change it because they're not mutable. That's an implementation detail that you do not need to care about when you're starting out. You probably actually don't need to care about it unless you're trying to write a book on how REST works as a matter of fact. It's the only case that I've ever encountered somebody like having a serious problem with needing to know that. So now we can talk about borrowing. Now we get the ownership and when you give it away you can't use it anymore and that's kind of a nuisance because you sometimes want to get to a value from several spots in your code. So a borrow is just temporary access into a value. It's basically more or less what you use pointers for in other languages. But borrows have rules about them that keep you from making the mistakes that are terribly easy to make with pointers. The most important rule about borrows that you're really supposed to follow whenever you work with pointers in another language but it's really hard to because you have to hold all your code in your head at once is you can choose. You can either have exactly one place in the code that can change the value or you can have as many places in the code as you want that can read the contents of the value. You can't have any other combination. You can't be able to both read it and write it from different places at the same time, not permitted. So the borrows syntax is the ampersand and then the name of the thing that you're borrowing. So there's the link to the long version of it. Again, in case I hadn't mentioned these slides are up on my site and will be there as long as I own that domain. So links are clickable in the PDF. So since you can only have one place in the code that changes the value or a bunch of places that can read the value you suddenly lose a lot of the problems that you would have in any other language. Additionally, how do you deal with things like use after free? Well, you have lifetimes. I started you out with scopes because scopes designate the lifetimes of everything that's in that scope. So I told you that a thing that you create in a scope won't be available anymore once that scope ends. Now, with lifetimes, you've got to make sure that you don't borrow a value and then try to use that borrow after the value's gone away. Sounds pretty straightforward, but it's as hard to do in practice as writing perfectly correct pointers in C would be. So if you want to be able to use a value after the scope in which it comes into being, you can give it away to a binding with a larger scope and that binding can keep it and then you can borrow it temporarily. The borrow can end before the owner ends. That's totally cool. So questions about safety before we keep going? Yes. So will rest allow undefined behavior like you'd get in C or C++? Safe rest? No. Unsafe rest? Yes. Because you need to deal with things like IO that might do who knows what. And so unsafe, we'll let you handle that. Yes. Can you borrow the value in a function? Oh, can you return a borrowed value from a function? If you create, so sometimes, if the owner, so if the value's owner was in the function, then no, you can't return a borrow because that owner goes out of scope when the function body ends. But if you passed in a borrow to something in a scope larger than the functions to the function, then that borrow can come back and it doesn't break the scope rules. Do I have an actual example? Not in these slides, no. I have 15 more minutes and a whole bunch of slides about how to find your community and how to use libraries. So I made the trade-off of not going too deep in these. So to use those 15 minutes on the pile of more information, you will also want to use libraries as you start out with Rust. As I've mentioned before, the package manager is named cargo. And the packages that cargo ships around and deals with are named crates, very cute. The index lives at crates.io online. And oops, that is an artifact of a previous incarnation of this talk. Check out doc.crates.io slash guide. And one question that commonly comes up with crates is can somebody unpublish a crate and do the left pad thing? Short answer? Absolutely not. Long answer, once you've published a crate, it lives in S3. Yes, we have backups. And the only way to remove that artifact that you've published is one of about four humans with the credentials would have to go in and take it out by hand. And those four humans with the credentials, myself included, will absolutely not take down something unless there's a really good reason. Really good reasons would include abuse, like flagrant abuse of the code of conduct, like you put stolen illegal content up there instead of code, or things involving lawyers. And if somebody shows up with lawyers, then we will also consult lawyers and figure out what the heck is going on before permanently unpublishing like that. There is a cargo unpublished flag. That just says, request that my users not depend on this version anymore. It doesn't actually take an artifact down. So now that you know that your library will be more or less set in stone and available for ever once you publish it, no pressure or anything, how to create a library. So you should use cargo for just general projects as well as for publishing libraries because it makes them very easy to publish and ship around and manage dependencies on. If you're just doing a thing that you're gonna run, cargo new with the bin flag will create a binary. You run the main.rs file and the main difference between a binary and a library is that a binary will have the cargo.lock file and that stores the state of all your dependencies the last time you had a good build. And so if you check in that cargo.lock file, you can force the people who use your code to build it exactly the same way you did. Whereas a library is gonna not need a main function because you're just gonna be calling things out of it. You're not going to have a cargo.lock because hopefully your consumer's lock file will lock the state of your library when they last found it working. And it's really a project design decision whether or not you check that lock file in. So when you run cargo new for either, it will create your cargo.toml which enumerates all of your dependencies, your license information, your author information if you publish your crate. Your main or lib file which you basically stick all your code in until you realize you need to refactor it into more files. And if you weren't in a git repo already it'll make your .git and initialize it because you really should be keeping your code in version control. If you really don't like git you can override that and force a different version control system but the Rust ecosystem as I mentioned before tends to be somewhat git and GitHub centric. So the way you can bring in a dependency is first you figure out what you want to depend on. You can do this by searching crates.io which is constantly being improved with better features, better flags and tags on crates to help you choose which one of several competing ones is appropriate. Search the web and check blogs for what other people have used to solve similar problems. One hazard there is check the date on any recommendation that you see because as a hot new language Rust has had a lot of people kind of dabble in it like make a weekend project and then abandon it. If it was a recent weekend you might be fine to depend on it. If it wasn't maybe you shouldn't be. So check the documentation and the license and the project policies to make sure it's compatible with what you're trying to do with it. And then add it as a dependency. You can either say your crate name and the version and then cargo will just go and pull it off of crates.io download that version and use it or you can specify a get dependency. This is great if you don't want to publish that if that library wasn't published anywhere if it's an internal thing for a company behind a firewall or you just want to make sure you pin the exact revision the exact commit. You can specify it that way. And then in your code you'll bring it in with extern crate and then the crate name. I'll use random number generator as an example which lives in the crate brand. And then you can just use the particular function out of that crate that you wanted. Or so questions about libraries I may have, oh I don't have the random number generator there but questions about generally how to use how to publish a library. Yes. Can you have different versions of a dependency? Yeah cargo is smart. So if I'm depending on let's say the latest MEO and then for some darn reason Rand decided to depend on an older MEO cargo would just kind of compile both and make it work. And so we have about eight more minutes left and I'd like to talk about how you can get involved and improve rest and level up with it if this sounds like the kind of tool that might be applicable for something you want to work with. So whenever you're getting involved with pretty much any project, please please respect others licenses. Remember to license your own code because just putting it in public isn't the license itself. And as you learn new ways of doing things and as you learn maybe things that a document was misleading or that you were confused by from your background please write down what you learned because somebody else is probably confused too and will also be Googling the same things you were. So if you want to improve your rest by reading a book there's the official book that lives at doc.restline.org slash stable slash book. If you want to dig into unsafe rest, work on a bunch of IO, do crazy things that you maybe in general shouldn't be able to do read the Rust Anomicon. It's a delightful read anyways. It's in a somewhat Lovecraftian style. And Jim Blandi and others are currently working on a book for O'Reilly that's more of a Rust from a C++ background whereas the official book tends to have a Rust from a Ruby background kind of flavor to it. So to follow news in the Rust world see when your favorite cool RFC is actually becoming a feature and so forth. The new Rustation podcast is an excellent resource especially for starting out. Rusty Radio just interviews various influential people in the community, asks them about what's going on and can be a nice deep dive into how certain decisions are made. There's a weekly newsletter and an official blog for more intermittent announcements. So following both of those will help keep you in the loop. To find practice puzzles, if you don't want to just jump straight in to contributing to a big Rust project, Carol has published a repo called Rustlings that are a challenge and instructions on what to do with it, how to fix it. And then you scroll way down the page and you get the answer to it or a hint or a suggestion. So those can be fun. The Rust by example book is, as the name implies, Rust taught through a bunch of examples. So if you learn well by poking at the sample code and seeing what breaks, if you visit that book online, you can actually execute the code in the play pin in the context of the book. So that can be a fun one if you like to get hands on right away. Any questions about where you can find a particular resource to go pick up more about Rust from? Nope, yes. So as a Python developer learning Rust, what are the surprises? Honestly, I would say that once you've read the book, the biggest surprise is how unpleasant it is to go back to a language without the strong type system and without the borrow checking. Because I will write bugs in my Python that I'm like, wow, if that was Rust, that would not have been possible to get to the point of executing the code. So that may not be precisely what you were looking for in terms of learning resources, but that's been my experience, yes? How much experience is there with Rust on microcontrollers, real-time OSs and so forth? So NOS is being developed in Rust called Redox. I do not believe it's a real-time OS and I don't personally know of real-time OS projects currently in Rust. My personal impression of the state of Rust on microcontrollers is that people will generally do kind of a weekend proof of concept project and blog about it, write about it, tweet about it. It's very cool. It worked on a particular nightly and then they don't tend to be like a long-term project yet. So the work that people put in on getting Rust, the Rust ecosystem better for microcontrollers seems to be kind of sporadic at the moment and it is a priority for the call. It's one of the things on the core teams list, definitely, but there are a lot of important things on that list. So I would say research what others have done on your particular platform of choice and pick the most recent walkthrough of how to do it and start from there. Okay, three more minutes. I can get through how to find a project and how to get more involved. There are a variety of ways to find some Rust code to hack on. Just look at popular crates as one option or you can do a GitHub search for all of the easy tagged issues that are in the Rust language. Generally, if a project is bothering to tag its issues as easy, they have some kind of mentorship pipeline and want new contributors to be coming in. So if you learn by porting existing code, there are a variety of porting tools available. You can use Corode, you can use, you can use the, what's it called, bind gen project to make Rust talk nicely with C++ and you can generally FFI out to Rust in the process of porting quite well. Also, you can search on and see which projects are blogging about looking for new contributors or post on the user's forum. Hey, I come from this, that or the other background would like to find a project, what are your suggestions? So you can also get involved. Please, if you find issues, file them. If you see an issue that looks like something you could address, have a go at fixing it. And if you're in doubt about what to do with an issue, hop into the Rust Beginners channel on irc.mozilla.org. So there are our IRC channels. Instead of a mailing list, we use discourse forums because that allows for better moderation and is easier to read the archives, which is really most of what you do with a mailing list anyways. And some unofficial communication channels include Reddit, Stack Overflow, there's a Gitter, there's probably some Matrix channels. The IRC is where you'll find all of the compiler authors. So if you're interested in getting involved with the community, find your local meetup. There's an LA meetup that Herman Redkir runs that's pretty good around here. You can check the community team calendar to see where in the world at what times there are Rust events going on. And you can hop into the community channel on IRC and ask around if you're curious. So if you want to go to a Rust-focused conference, there are several. There's Rust Conf, generally in Oregon, generally in September, Rust Belt, Rust, generally in Pennsylvania, also in the fall. And Rustfest.eu, which I think is actually coming up in April this year. They have them at various times if you want to go to Europe. So any questions about where to go next? What resources to start with as you go out and play with Rust? Yes. Is Create.io written in Rust? The website is, I think, I think, don't quote me on this, it's actually an Ember thing. That's, it just runs on Heroku and I don't think Heroku has good Rust support yet. Rust is not exactly something that you would want to build a web app in right now. It's like, kind of like building a web app in C or C++, it's, I think it's actually a Python site. So yeah, thank you very much. And if you have any other questions, you're welcome to reach out to me on whatever media is convenient to you. Any people first? Did that work? I don't know whether I'm supposed to wait for an official scale, go ahead or what. I'll give it maybe a minute. And if anything, I'm going to be too loud. That would happen with or without this mic. The more excited I get, the louder I get. So we'll see. I guess if I am bursting eardrums, somebody's scream or, oh, Zubair's here, now I can start. Is that a Seth hat? Is that the theme? Oh. There's always a talk about Seth and I think they have a squid mascot. That's why. Yeah. Is it? Okay. It's time. All right. I am Kelly Heller. I'm going to make a sales pitch for Go. It's definitely on the sales pitch side, so I certainly have demerits for Go in my head and some of you will be able to guess what they are once you know a little bit more about my background, but you can ask me about those at the end if you want. If there's no other questions, somebody raise your hand and say, what's bad about Go? So I don't want to say really anything about myself except what's relevant to this talk and probably two most relevant things are I love to write code. It's more than a love. It's frankly an addiction and I get paid for it though, so it's left untreated. And the other thing relevant to this here now is I love Linux. I love open source and I love scale. I found these in my closet. I put one on this laptop. This laptop is not eight years old or however many years, but these are scale 10x stickers. I have been attending since scale 7x, so yeah, I love scale. Yeah, oh, and this is from Linux Chicks from last year. Thank you, Linux Chicks for this, my bling. Okay, my authentic Go story is that I approached it with heavy skepticism. I was a skeptic and I was a very specific kind of skeptic. I was the grumpy, curmudgeony, grumpy coder, gray beard, battle weary skeptic. And of course that has nothing to do with Go. That is only a function of years in the industry. My native language is C++. My husband asked, are you explaining the boat? I didn't know if it would need that. It's just C++ is gigantic. It's an ocean liner of a language. And so when you have a language and you've been successful with it for a while, two things happen. You see a bunch of fads come and go and then when they go, you think, oh yeah, I'm so glad I didn't jump on that bandwagon. I'm fine, I was vindicated for staying put. And you just get really good at the thing you're doing. And with something like C++, you're never lacking for the language feature that you could think of, so you're just good. And you build up a whole bunch of tricks, idioms, design patterns and you don't wanna lose them and you shouldn't because that was a big investment. So when I look at other languages, I don't really care about aesthetics. This is, you know, C++ rip here, sorry. I'm immune, I'm completely inoculated. So none of my sales pitch is about how go looks or anything like that or how it feels or oh look, you can read it like an English sentence or I don't care. So, oh and one other minor point here while I'm hopefully moving off of the topic of C++. When you're brought up in C++, there's another thing you know about and that is language lawyers. So if I have language lawyers here and it's good because it teaches you to be very precise about what you're gonna say. So in the interest of precision and I nod to the lawyers out there, I'm gonna say things like in go you can do this or go comes with feature X and go lets you do this. Usually I mean the language, the actual language independent of whether or not you would maybe go out and write your own compiler for the language or your own, you know, runtime I guess for the language. But sometimes I do mean the entire tool chain and right now there kind of is one tool chain that when you get the go distribution, you get go the compiler, go build and there's a linker in there too but there's as far as I know you never type go link but you get go build, you get go doc, you get go test, you get go format. And so yeah, for the language of lawyers out there when I say yay go gives me this feature, usually I mean the language but sometimes I mean the tools and so there I said it, don't call me on it. Okay so I said I don't care about really the aesthetic look and feel of language. Where my head likes to live, I really like to think of my projects at a zoom out level. Any individual file could look ugly or pretty but I care about across all the files that I have, some of them are hopefully part of a sub library and then there's sort of higher level library on top of that and then the libraries start to group together and at the very end you have some executable layer that hopefully just initializes a few things from your libraries and starts some loop and there you go. So really what I'm looking for is if you're kind of trying to tell me like hey, don't use C++ anymore, use go or don't use C++, use Haskell or Rust or whatever, what I really wanna know is can I not, what are you gonna do for me to make sure that I'm not on the left side of this and that I can control being on the right side diagram and what I always say if people ask me oh hi on Earth do you still like C++, my answer is I can, if I think of a design I can express it and I can enforce it and that's what I look for because I think a lot of languages, you can start with this, like I know how to start with this in Python but I don't know how to enforce it, I don't know how to say oh yeah, you know clone me, fork me on GitHub and then submit a bunch of PRs and then then not have it look like this because I can't do all the tricks I know to just stop somebody dead in their tracks like it won't even compile if they try and start adding bi-directional dependencies and stuff like that, there's, anyway. So this is what I look for. So after I fell in love with Go and I wouldn't shut up about it and I told all my friends and then somebody said you should give a talk, so that's how I got here. I started thinking well why, you know, why me the skeptic, why am I in love with Go and Go is kind of opinionated and I tend to not like opinionated things but it just feels like they made all the same opinions I would have had so it feels good for that reason and all of these tricks that I've been talking about they're still there. And so here's where, you know, I don't know. Do I have C++ buddies in the room, anyone? Woo! Okay, cool. But not the majority, probably like what, 5%? But so if you're, for the rest of you, here's where maybe if you look at this list and think do you see your favorite things on here? Maybe you like some of these things too or if not, maybe think in your head what's your wish list? Like whatever your language is that you like if it's Ruby, if it's PHP, if it's C, whatever. Why, why? Because that's what I tried to do after I liked Go. I was like how can I reverse engineer and articulate why it's still, you know, fed all my needs. So I do not like to compromise on multi-paradigm and yes, I do functional programming in C++. If that sounds shocking, get modern, get modern C++. We have lambdas, it's awesome. We have a networking library, ASIO, that's very functional style. But you know, some things, you just wanna function, Java. And so, you know, I want that in the language. I wanna just write a procedure or and then I also, you know, use some tried and true like classic for design patterns. So I don't like to compromise on those. Type safety. I feel like type safety has been winning lately. But that's my opinion, I guess. And then data hiding. And that could be with or without, you know, compiler type checking. Data hiding, just that ability, sort of what I was talking about before. If I have something in C1 and I don't want anything from A2 to be able to talk to it, like, what do I do? Can I mark it private to a module, private to a class, just various mechanisms for reducing all those arrows in the diagram and then making sure they stay gone. So then if you like these two slides, the logical next question is, oh, let's have a step by step. And that was sort of my question but I failed that grossly overflows the bounds of this talk. I would love to talk about each one of these exactly how they can help you. But I decided, since I can't do that, pause. Everybody go, we'll do three years of study and experimentation. And then, okay, now we've all got it. So these are the things I care about and has all of my power tools that I care about. Oh, and I forgot to mention, we're almost done with the intro, sorry, I might have gone a little bit long. But this talk has three parts. It has the light-hearted intro that's also fairly light on content and we're about done with that. And then it has a Act 2, which is go giveth. This will be Act 2. And so I just hope to put up a bunch of code and just show and convince you that go has these things because I don't want you to have to take my word for it. And I don't want you to go home and be like, exercise for the reader. Like, I hope to show you. And then Act 3, which is the conclusion, is go takeeth away. And this gets back to that opinionated part. There's definitely things that go doesn't have, some of which are really interesting decisions and it's really, that's almost the main linchpin of why I was so excited. It's like when you tell me go has these things, I go, well, okay, cool, but I already have these things already. But then when I learned about the things go doesn't have it, it suddenly became really like, oh, I have to have this language now. I have to have it. And so here's why. Probably, I'm gonna guess everybody in here does programming. I'm sure I could even come up with some obscure definition of how like writing a certain kind of email or I guess using a spreadsheet is like programming. So I'm gonna say everybody in this room is a programmer, I don't care what your title is if you're a manager or QA or whatever. As a programmer, oh wait, wait, wait. So this is the crowd participation part. Okay, without harming any laptops, secure your laptops, raise both hands. A little higher, okay, that was just to stretch. Okay, sorry. Okay, oh good, I got a clap. My husband said people would leave after that. I just, I'm somewhere in between, I just figured nobody's gonna raise their hand again now. But, okay, so last question and this one's for real. As a programmer, show of hands, have you ever had an argument about a programming language? Or, right? And I'm gonna say, so that was the whole room to speaking to the video there. And if anybody didn't raise their hand, it was just because I tricked them earlier and they were taking their revenge. Okay, so that's why what Go doesn't have is so exciting and so refreshing. I've had so many arguments, so my big ones that I've had to sort of belabor the point over and over again with training juniors or just recalcitrant seniors or what have you is, you know, when are you abusing exceptions or when is it the proper use of exceptions? Why is composition really, you know, if you can do composition over inheritance, why should you, white space and all that stuff, I hate that, I just hate it, I don't care, I will put my brace wherever, I don't care. Function overloading compiler warnings, which if you don't come from a compiled language, that one doesn't pertain to you, but it's like, oh, you know, the compiler is warning about this line of code, yeah, that's fine, just leave it there or whatever. And then others are like, no, you have to fix the warning and then you get a different set of warnings on one system than on the other or one version of the compiler than the other, all these things. So, that is, oh, pretty much the end of section one. In retrospect, I realize I shouldn't have been surprised of any of this really, and that's because where did this language come from? I am just so, you know, we're at a Linux conference, so, you know, we're not worthy, and I'm so glad, you know, just like when Linus, you know, you thought Linus doesn't owe us anything, we have Linux, and then we got Git, and it was just amazing. This same thing, it's like Ken Thompson, his handle is Ken, he's the Ken, he got a three letter handle before any of us were born, and, right? Before any of us were born, just own it. And also, the book, which this is an amazing book, you recognize this name right here, this book author, and this is the book that basically convinced me that I'm in love with Go, and so none of this should really be a surprise, and this slide alone is probably a good pitch for why, why Go. Okay, so I was going to use the Go Playground, but then the network was being weird, so I have it all locally, so I'm using Emacs, oops, which I didn't launch yet. So, sorry, I should have had this one up already. Can't I, come on, task more, go away. Well, let me just run this, this is, okay. Why is my task bar there? And yeah, sorry, I'm on Windows. This computer has VGA, so that's why I brought it. Can I move my task bar then? It's supposed to be auto-hiding, now it's still not, sorry, guys. So, somebody said unlock it, but I don't know. Well, that would help me drag it, right, but then it still wouldn't. It was cooperating before, but maybe it's weird because I'm plugged into the network, or the video cable. Okay, anyway, as long as, now where's my compilation buffer? Shoot, maybe we will use the Playground. Let's try one more time, yikes. Okay, well, let's see if the Playground will work then. Sorry about that, thank you for your patience. All right, okay. So, the code on these slides, it's mainly in the slides for the sake of if you wanted to look at the slides after the fact, because I think it's a little hard to read. So, in the Playground, which I should then be able to make it bigger, is this, can people read this code? Is it pretty? Dark, try dark. Yeah, okay. Shout out to, this is actually a Chrome extension called Better Go Playground. Otherwise it wouldn't have that dark option, so thank you, Better Go Playground. Okay, so here we go. This is just to see, just to see any old kind of go code on the screen. So, here you go. This, can I run this already? I should be able to run this. Okay, so we declared some Boolean. We're printing it, there you go. This is again, just entirely meant as warm up, just so you can have it in your system. What does go look like at all if you haven't seen it? Yeah, okay, so good question. Oh, and by the way, yes, through this whole part of me trying to live code and not stub my toe, questions, and if I don't see your hand, yell question or whatever. So, this is the short assignment. And so, we are doing static types, so that is definitely a Boolean and I can't assign anything else to it. It is, you know, doing type deduction. I hope that's the right word. Who's the language lawyer? If you want to be explicit, so here's the way that you could make it explicit and what it's gonna look like is the type comes after. And I know you were watching the Rust talk too. Same as Rust, as I now know as of today. You put the type after the name. So, and then you don't use this, the short assignment operator or the short definition or whatever it's called, then you would go like this. And, okay. So, this is just creating data, creating some local variables. So, a function. Again, also very familiar from pretty much every other language I know. So, keyword funk and then you give your function a name and then you have an arbitrary list of arguments. Again, the name of it is text, type is string and then the return type of your function right here or if it doesn't, if it's essentially void, you could just leave that out. So, now we have this function. It's using something from the strings package which gives me a chance to point out that another thing that I know everybody likes to look for in a language as it should be is what kind of batteries come included and Go has a lot of batteries included. There was a talk Thursday, are the pro-core people in here? Somebody did the talk with Postgres using Go and they also mentioned that all the libraries were ready to go. There was a Postgres connector and they were doing something that required cryptography. There was a cryptography library that was already there. The standard libraries are great and they are heavily cross-platform and they make it very easy. There's a registry of third-party packages available that's also great but even just what comes with the language distribution is phenomenal. For HTTP, for JSON and it has its own proprietary marshalling to go streaming if you want something faster than serialized to JSON, a lot of stuff built in. Okay, so the function, hopefully, that doesn't really look surprising either. We're taking text, trimming off any white space from either end and then if we got an empty, if we didn't get an empty string then at that point we're saying this string has content. The only reason I wrote that function is because I wanted to do one other thing which is your most common collection type that you would use is a slice. And really, so there's also such a thing as an array and the only difference is that the array would be a raw array, contiguous memory and you would give it a size and then it's not resizable. A slice will create an array under the hood and then your slice is a pointer to the underlying now sort of opaque from you array and a length and it can be dynamically appended to and then of course it internally will resize the or create a new array and copy things over and anyway. So this is a slice of strings and then I'll do just for loop. Let me not mess up to iterate over this slice. Range one. This for now. And yes, I'm using printlin. There's printf with your typical formatter strings and even some cool ones that automatically quote for you so that you're not doing weird stuff like slash quote all the time. I don't know, maybe other languages have that but let's see print for anything. Oh, I didn't mean to print the line, I meant to print call the function. But this is all. Okay, so that was just so that everybody could see what Go looks like if you haven't seen it before. Now, please. Oh no. Okay, I'll open it in a new tab. Okay, type safety. Let me, well, yeah, let me just talk about this one, sorry. The internet said that it was more fun to watch somebody write code than to read it on a slide but maybe they didn't meet me. I don't know. So, okay, so what I was attempting to show right here, probably everybody knows how type safety works but just to again sort of get warmed up and see it in Go. So we work for a veterinary office and when we ever send an email or print out a webpage welcoming the user, we're welcoming Mary and we decided to be super cute and inclusive of our actual veterinary patient who is Mary's dog and so if Mary has a dog then it's saying it's gonna print out to Mary and dog. Yeah, I know that's not great. It should say like and her dog but then you're gonna ask me to internationalize it too and that's just not gonna happen. So then you wanna rewrite the function and realize, oh, well, some people have more than one dog so instead we're gonna write it to take an integer and if there's greater than zero dogs then we're gonna write the salutation to Mary and three dogs or however many dogs. And so I actually, to make sure I was being honest, I did this in Python also and in fact, if you write the second version and then you paste it over your existing one so that it's still salutation, Python it's not compiled, it's not as strong typed. It will still let you make this call and then it'll print out to Mary and true dogs. And so I know this was like a little contrived but at the same time I feel like we've all gotten that email to like Mr. Null or Mr. and Ms. Null or something and this kind of along those lines. Okay, so Go has typed safety. Functional programming, let's see, can I actually open this? So if you do functional programming I consider this sort of hello world. It won't be shocking at all. If you don't do functional programming this looks very strange like the first time you see recursion and you think that can't work. So this is what it looks like in Go. We have as before keyword function we're defining a function. Now there are no arguments and now this whole remaining bit is the return type. So we have a function that takes zero arguments and it returns a function. Yeah, and when you have the function that is returned you can call it with zero arguments and get an int. So this is a closure. The closure will, actually I like this better with negative one, the closure when this inner unnamed function is constructed and returned it will capture counter value at negative one and then that becomes part of the closure. So here we're gonna call it and so you can maybe, oops, don't do that, expect or not expect what is about to happen. What did I do? Okay, and we'll run it. And so there we go. So yay, functional programming. I don't know why you would ever write this one but I do have a better example that I have used in real life and found it to be quite elegant. If you imagine that make counter is actually, we'll call it make file iterator and inside there you initialize a file handle to an open file and then every time you call your iterator, it or whatever you wanna call it, you get another line back from the file that was open and then you can actually do something close to RAII that was for like the three C++ people where inside of the closure when it gets to the last line of the file, it will close the file and so it's very clean. The user code ends up looking very much like this where you just say, make my file, line, line, line, line it or line it or line it or whatever and then when you finally get it returns null or whatever you just stop caring about your iterator and you're done. So let's see. I will skip over this other thing but it's pretty cool if you're ever looking back over the slides. This is another example of using a closure here to sort of encapsulate a map. And so that's an immutability trick. It was from Stack Overflow, so there's the link. Okay. So Go has type safety, Go has functional programming, Go has object-oriented programming. This, it's super important but this is like the longest most painful example. So let's just see. Okay. So this is what making your own type in Go looks like. You'll notice that the keyword is struct. It's not class, that's all you get. It's struct, so that's cool. Again, that's sort of the opinionated thing. If you're used to C or C++ and you can declare it as a struct or a class and what's the difference? Well, some certain default syntax and otherwise nobody knows except the Visual Studio compiler is weird about it and so it's just struct. So this is a class definition and I have chosen to abstract a classroom and all my classroom does is it's basically a container for desks and so we have a count of how many desks are in the classroom. So let me just say some interesting things about objects in Go. Right here, the fact that this is a lowercase D means that it's a private data member. I thought that was pretty cool. I've since talked to people that find that obnoxious and not obvious enough but you know, and I wondered about that, thank you. This man just said there are languages and alphabets in the world that don't have the notion of uppercase. Thank you. Cyrillic I believe is one of them or at least I was told by a Russian coworker that they have upper and lower but in newspapers or in some contexts they don't use it and so I was sort of teasing myself that same way because you can write your code file as UTF-8 encoded so you could write a Cyrillic Go program and then I don't know what happens. Is everything public? Is everything private? I don't know, does anybody know? Has anyone done that? Anyway, so yeah, so that's how you toggle basically public and private. Other argument you never have to have again is why is protected visibility evil? There's no protected visibility here but there's also no implementation inheritance so it's a moot point. Okay, so then if you want to add a method so we're gonna instantiate a classroom and we're gonna call add one desk. Your instincts are if you're from Java or C++ to try and add the method somewhere up in here in the body and that's not how it looks in Go. So how it does look is right here. It's the same function syntax as before but then you add something that they call a receiver and it's essentially this or self the Go people don't like for you to say that. And I don't exactly know why. I read the explanation, they wanna emphasize that it's more about writing a function on a receiver than having this. I don't know, it was kind of lost on me but so and they also don't like it if you name it that. But anyway, old habits die hard I guess. So this is now by having a classroom receiver now we have a method that you would call in the expected way down here. So there is a lot to say about how Go does object orientation and I don't know how much people have the stomach to listen to me blather or struggle through the code but let's just do one, let's just do another example anyway. Does anybody have any questions so far on this one? That's actually kind of nice, it's funny cause even now 10 years in with C++ I forget to do this and I hadn't even noticed that that you don't, yeah you, again similar to in the Rust talk or no, I misunderstood her, nevermind. Nothing about semicolons in Rust. Semicolons exist in Go but only in, and you can type them in certain places and the code will still run. Yeah, yeah, thank you, like the for loop. And even here, like I just added that one and it was okay and I can add one right here and that's okay but you, two things about it. You rarely need them and in the one case this gentleman pointed out in a for loop when you have your initialization and your test and your increment statements, those you still need the semicolon to know where one ends and the next one begins. So you rarely need them and then in the other case right here if I click this big format button, they will go away, or they should, let me see, there we go. They went away and I'm gonna talk about Go format. So basically since Go format took them away, you should feel bad, I don't know. They weren't necessary, that's not the official format. Okay, yes, so I guess we do have an appetite for this. So how would you do inheritance? Well I also mentioned yeah, no protected data. There's public members of a class and there are private members but no protected. What happens if I want polymorphism? Let's just, let's see, tell me what you said first. I wanna use your words too though and then I'm gonna, you said how do you do inheritance? Inheritance or extending a base class, right? Okay, so again, arguments you never have to have if you're coming from C++ or Java. So the reason why I wanted to change the word to polymorphism is you're basically, correctly stating that there's two kinds of inheritance. There's interface inheritance and then the extend, which I always taught myself in Java that when I see extend that means bloat. Extend, which is implementation inheritance not interface inheritance. So in go, you can have interface inheritance and then they have this new concept sort of that they call struct embedding, which is so fun. And this is where, and I mean that because I just love the idea of not having to fight people about composition versus inheritance. Struct embedding and I'll try and do one up here fairly painlessly, I hope. Struct embedding is composition but they have so successfully disguised it that you will find multiple blog posts in the world explaining that this is how you do inheritance in go and it's composition. But I consider that like a huge win that they've sold it or they've tricked so many people into being like, yay, I can still do implementation inheritance. Yeah, what's your question? Sorry, you know what? I meant to say also when I mentioned the language lawyers and that type of thing that I am not covering go routines and concurrency because, and sorry, if like half the room wants to leave, you can, I won't be upset. Okay, well I might have some information for you at the end on the resources slide, but basically there's an abundance of information out there on that and I sort of wanted to, none of that was what convinced me that I needed go so I'm just speaking from the parts that I like and, but there are great talks particularly by Rob Pike, one of the creators. Okay, yeah, I will say a few remarks about that at the end. So okay, but yeah, I'm coming more from a comparative languages sort of tactic here. So back to this man's question in the front about interface polymorphism. So if I wanna also say that I have an office and it also has desks, oh, I probably should have corrected a bug in this first. Let's go back and do that, oops. So you may have noticed when I was running this earlier and we had a desk and I figured this default printing was good enough to get the point across, we had a desk, it was initializing desk count to true when we instantiated the classroom and we printed it and you can kinda tell roughly that that was a desk with a desk count of two inside it and then we called add one desk and then print it again and it still says two. So something about my plus plus desk count didn't work. So, and that's why I had this comment here, this needs refinement. You can have a method on the objects of your type and if it takes the receiver by copy, then nothing happens to your actual receiver. So we need to take this by pointer and now it works. And so there's a lot of subtle differences here just like off by one character, so to speak. I already talked about how the lower case versus upper case toggles public and private. Now you can have a method both called the same. You notice I did not change, all I changed was that one character, I did not change the call site. But the receiver type will either be passed by pointer or passed by copy of the object and that will basically decide whether this method, let me put it this way. If all the methods on your class look like this without the pointer, you have an immutable type which I think is very powerful and nice to know that that's possible. But in this particular case, we're intentionally trying to mutate this. Question, yes, the go-bot people, you should talk to the go-bot booth. They have go running on Arduinos and so forth. Go compiles to machine code on a number of architectures. The only, it compiles fast and it compiles into a binary that executes fast. But the only sort of remaining hiccup criticism that people would have adoption issue is that it is garbage collected. So you can have a GC pause and I don't, I am not an expert on the details of that. Okay, so now we fix the bugs. So now back to the polymorphism. So now we have an office which has the same interface. So I have a classroom that I can instantiate and add desks to and I have a office that I can instantiate and add desks to. Room two is an office, room two, sorry. Anybody sitting here going, I could type way faster than her, you probably could. Okay, so these share an interface. So if I want to make a function that just a function now, we're not worried about methods. I just have some other code, whatever. Some other code that needs to operate on a desk holder, let's just say, right? Anything that holds a desk. Then I'm going to write a function that operates on a desk holder and we don't know what a desk holder is yet. That's the punch line. But this is what I want it to look like. And this, and so when I operate on the desk holder, I'm going to add one desk. And I want to be able to call this function with either. So operate this holder. I should have made that briefer and I could pass in the classroom. Or, sorry, I don't have my E-Rex keyboard now. So I'm like, I don't know any shortcuts to make this go. Okay, so how would I do this? And so this, I can make an interface, a type desk holder interface. So when we declared a struct up here, the only rows of code that you're gonna see in between the struct open bracket and struct close bracket is gonna be data members. Because as we saw, you put the methods elsewhere. It's the opposite when you declare an interface, the only thing you're going to see are methods signatures. So what we're trying to capture here is any type that is capable of me invoking add one desk on an instance of that type. Okay, I think this is all lined up to where I can run it. Okay, yes, and I didn't call any printfs or anything. I guess I could at least put one here to show that we entered this in operation. So I was able to successfully pass both a classroom into this polymorphic code and an office into the polymorphic code. And so this is the interesting part about this. And this starts to segue into controversial items about Go, which is, I declared this interface. And so we know what we can expect inside of operate on desk holder. I did not have to go back and make it explicit, any intent, explicit intent to say that classroom is a desk holder and the office is a desk holder. On my theme of not having to argue with people, you can't say that classroom is a desk holder. There's no way to tag that onto here. I do miss the explicitness, but this means that nobody can abuse inheritance in really weird ways where I've seen code bases where every object, subclasses, let's say you work at Acme Corp. Every object subclasses, official Acme Corp object for no reason that I can tell and they're never manipulated via a pointer to that base type. And I go around asking, why do all these things implement that? And people say, well, because it is, it is an Acme Corp object. But if none of the calling code treats it as such, that's so beyond irrelevant. Okay, yes, yes, yes. Because again, type safety. So let's go ahead and change it so that office doesn't. And let's just see what happens. Yeah, add one desk. Thank you, no, awesome, thank you. Okay, so I went over on my code demo, sorry. And now there's one other thing, and this unfortunately I am just gonna have to leave it as sort of exercise for the reader. But we talked about can you do implementation inheritance and what you do, because you'll notice there's still duplication here that's probably bothering some people, is that essentially the office and classroom both have desk count. Office and classroom both have this call to desk count plus, plus, so don't we wanna bump that out into a base class? No, but you do wanna bump it out into something. And so that's where Go has struct embedding, which I'm not gonna demo right now, I'm sorry, I took too long and yeah, I'm me a copa, but it's really, like I say, it's awesome because you can't have implementation inheritance, but people think you can, so it's good. So you have all, everybody's happy, some are happy in their ignorance and some are happy in their wisdom, but let's see, so, oh, testing, yikes. It gives you some awesome built-in testing. If you get the go distribution, you don't have to decide, am I using JUnit, am I using CPPUnit, am I using GoogleTest, am I using NUnit, whatever C-Sharp has, maybe I already said it. It comes with testing built-in and not only that, but they've, again, testament to these guys have seen some stuff. They put in things that are really important to a production, a large cooperating production team, which is, so here's how you would just have a test function. You could have a file of code filled with these that take this built-in testing type, which is really just how you output your pass and fail and all of that. That's just, you can write a test, yay. But the other really cool thing, two extra cool things are, we had add one desk, go test will know and go doc will know that if you have a test and you name it after a method or a function that's in that same package and you just add the word example to the front, then this becomes living documentation because every time you run your test suite, it makes sure that this compiles and if you add this output comment, it will also verify that the output is still this so you have sort of a pass fail and then when you run go doc, which is akin to Java doc, it will pull out this code in a nice little example snippet that people can learn your code base and just copy and paste your example code and you know that it's not stale because it was part of your test suite. I think that's really fun and compelling that that was built in. Also benchmark, it does some really neat stuff where if you just put benchmark on the front of your test, then when you run the test suite and you actually have to tell it the benchmark flag because it's gonna make the test take a little bit longer to run, hopefully not much. It will run all the benchmarks and do really interesting things where it will call the function over and over and over and take an average and it's gonna sort of adjust on the fly based on how long it's taking to run your function, whether it thinks it has time to run it a million times and take the average or just maybe a hundred, but it'll do like best effort and so you will right from the start have baked in performance testing, which I think is amazing because it's one of the 97 things that all architects should know that you should test performance from the get go. Okay. Oh, I missed my opportunity for a joke. Go format. Once upon a time, there was a language that tried to legislate white space as part of the language. It's called Python. It's not around anymore. I learned about that. I was very optimistic about that. I thought, what a cool opportunity to really just stop these stupid arguments, just make it part of the language and be done with it and that's what I thought and go Python and then still happens to me pretty much every time I download Python like quick and dirty on the fly and open it in some random editor. This happens like every time. So what go got right, in my opinion, is that it does sort of legislate formatting, but it's just by convention and your code will run as opposed to this. Your code will run if it's badly formatted, but everybody, because I guess we've all been scarred enough by now, we know to take our medicine and you just run go format and it's built into every IDE for go and it's not a problem and everybody lived happily ever after. And it has an extra flag, go format, simplify where it helps you, it does other cool things, which I think are really clever and neat. It'll just catch sort of extra verbosity that you may have typed in and remove that too. Compiler warnings are not a thing. Everything's a compiler error. I tried really hard, I thought, even though I read the words, there are no compiler warnings, I thought, there's gotta be something, there's gotta be one little thing and I tried a bunch of wacky things and I couldn't find any and by all authoritative writing there are none, but I just couldn't believe it. So the one that happens a lot though is obnoxious at first. If you have a variable that you don't use, this won't compile and it'll tell you declared but not used or something along those lines. I hated that at first because I do, especially since the go compiler is fast, you can iterate fast and so you might be sort of just stream of consciousness and I need X because I know I'm gonna do this thing with X but you're like let me run this and then it won't get past the compiler so then you comment it out just so you can do a build cycle and it gets a little weird but then, I don't know, at least in my case I just sort of adapted my habits I guess because I learned to love it because it saves you from this one. If you're using the short type deduction assignment that actually creates result so then you get, sometimes it's quite easy and your eyes don't see this bug where you think you're flipping result to false and returning it but this will be a compiler error because you're actually creating result again in this inner scope and it's just shadowing. So I learned to love that one as a compiler error but here are others that and you can see them yourself in the go playground if you want if you click the go playground link later and just click run all these lines will turn red so much fun and if you're coming from C or C++ you're probably used to these being warnings except for the top one of course and the top one, it's very interesting. If you think of these as pound includes for other header dependencies it's a compiler error to essentially pound include something and then not use it but that's part of how they got compilation to be so fast and it is amazingly fast. You'd have to find the talk by Rob Pike or one of the others where they talk about compiling billions of lines at Google or whatever and it compiles in seconds and so that's part of that and that's also really cool because you end up with this weird cruft in your C++ programs where people can never remember as they're deleting the code to delete the pound includes and then anyway, there's no exceptions. I won't even ask for any show of hands because this one's a holy war right but I thought, I don't wanna incite like exception versus non-exception battle in here. This is go defending itself on this note. Errors are an important part of a package's API and failure is just one of several expected behaviors. Oops, I went the wrong way. And expected, I really like that idea. I think it's kind of an ideal but if they succeed, if this is the outcome, if people learn to just treat an error coming out of your function as one of it, failure is an expected behavior. I think that's pretty cool because I have definitely spent a lot of my time in code reviews telling people, did you know this thing you called can return an error? And you better say no because you're not checking for it. So you have to, so this is just idiomatic go. I pulled out some, again, giving you an idea of the richness of built-in libraries. This is the time zone library, the email, I guess, library. I just kind of gripped for things that returned errors and OS user library and so this is the pattern. So what Go gives you instead, which is still better than your old school C of return an error code, is you have multiple return values. So the convention in Go is you return a result and an error and then there'll be a lot of checking and there's a semicolon of error not equal to nil, meaning that the call succeeded. And I think I'm already probably over time so I won't say too much more about that. Again, I touched on for testing, they have some really cool built-in Go test and you don't need your J unit, your Google test, your N unit. Another thing you don't need is a mocking library and that makes me really happy. And this goes, this actually touches on that struct embedding and what this is showing, just briefly and this is like my last little Go take it away and then we're done. What this is showing is so if you imagine that this is a test function and it's not because in Go Playground you can't run tests but imagine that this is some code that you're testing and this is somehow part of a test suite, you have a function that takes a type OS file info and so you wanna exercise this code without having to instantiate an OS file info so you essentially wanna mock and you wanna mock an OS file info. So what you can already do in the language itself, no mocking library added on is you can essentially make a fake type and you plop this name of the real type inside it and this is that thing that I was saying is called struct embedding which people also refer to as sort of inheritance and so now this guy is eligible to be treated as the file info and you only have to implement the method that you want to quote unquote mock and this is a little hand wavy here but you can run it in Go Playground and it will work and hopefully you'll be really excited about that. One thing that crossed my mind and so then again go to Go Playground and try it yourself is oh well all I implemented on here was size so it does successfully execute this code and call size and I can verify that it did my version but what if inside here you call one of these other things, you call isdir or something else and you didn't implement it, then it crashes so but that made me happy because it validated my understanding of like how much magic is happening here and the answer is like not a lot of not magic which is good, we don't like magic. So parting words, cleanest code is a code not written for everything else there's go, resources. I think the guy that asked me about concurrency left but I have been, I've read this book and I've been reading this book and I actually think that if you really want to get right into Go Routines, the first running example in this book is both excellent and also practical, something you might actually write in production code but I highly recommend both of these books. Everything else on here is self-explanatory except this, everybody go here, this, if you think that the gopher is too goofy and happy and you want to punch him in the face, this Renee French that designed the gopher, you will be shocked her actual artwork, it's so, these are her words, gritty and creepy and it is gritty and creepy but it's amazing so go check out her other stuff that's not a grinning toothy gopher and that's it. It executes when you run your test suite. Oh, did I pass it or was it? Or no, it was in the other one, this one, yeah. That's, it's just how Go test, it's one of the things that's baked into Go, yes and if you go to any proper Go package and look at its documentation and like I said was like Java doc and you'll see the little things that say example and that's where they're coming from. Yeah, it's really neat. Okay, do I, I need to clear up. Any other questions, I guess I'll step outside. Thank you, I was looking at the next speaker and I thought you were with him and I'm like, I gotta get out of the way but I do gotta get out of the way. All right, is it time to begin? What time is it? I got 20 seconds, all right, I'm gonna take my entire 20 seconds to just like chill out here on stage and literally not think about the 25 people that have had this on their ear and haven't washed behind their ear and whatever's going on back here bacterially and infecting me. It's, yeah, it's, I wash behind my ears if I'm gonna get a mic like this but not everybody does, it smells kind of funky. Anyway, thank you all for being here. I'm super happy that all of you here, it's wonderful, last day of scale, right? Yeah, last day of scale, right? Second to last talk of the entire week and everyone's gone home except us. We are the hardcore, the intrepid. We're here for this talk and we're gonna be here for the five o'clock slot, right? We're all gonna go see that talk and we're here to do it and do it right. So just thank you for showing up, right? I've done a lot of last day of the conference talks and it's crickets most days and it's sad but. Okay, so I'm here to tell you about Go, a language that I have discovered recently and begun using in ways that I didn't think that I would be beneficial. It's a wonderful language and I want to encourage all of you to use it. Who here was here for the previous talk? Okay, so you guys all know about Go, so some of this is gonna be boring for you, right? We're gonna, you know, we'll bang this out, we'll be out of here early and we won't have to do anything about it but specifically the features of Go that I want to talk about are about cross-platform development because it's magic in Go, it is so wonderful. So for those that haven't programmed in Go, this is what a Go program looks like. It basically, it's fairly C-like, it's a declarative language and here's Hello World in Go and it's not that complicated, right? You import a package, you declare some code and you're off to the races. You're going, literally. But the one thing I want to tell everybody that's interesting is that anyone who's been in the online space and computing for more than 10 years, anyone remember what the 90s were like, the vitriol, the conversation was, I like my platform, I hate your platform, therefore I hate you. That was the nature of the dialogue 20 years ago and that's all come to an end because now in a world of connected microservices we're all talking HTTP, I don't care if you're running on Windows, I don't care if you're running a BSD, I don't care if you're running on AIX, we're all talking over HTTP and as long as the microservices all fit together, it's now I like my platform, I can see why you might like your platform and as long as we can collaborate and get together, we're all going to win, right? And this is a major change in mentality. I mean, I remember the nature of the debates and how acerbic they were 20 years ago and I don't see that anymore today. There are still some people who feel that way but they're in the minority and they're going away and that's great. We all are winning because we're all able to leverage the best platform for what we're doing today for what we want to accomplish and the best talk is all about the fact that Go is a great language for achieving multi-platform development. So, Go, we already covered this, it's a very simple language, you can build code, you can write code, but you can compile it for multiple environments, right? So, this is Hello World and Go. If you want to build your Go program, you install the Go compiler, you literally just say go build, main.go and then if you look at the file that's produced, you get an executable, right? It's simple. The compiler itself actually has build tools, the logic that we normally would rely upon make to go and actually assemble all of our program built into us. You just say I want this thing to be an executable, build me an executable and we're good to go. But, Go is also excellent for DevOps. Who here is in systems management, systems engineering, system administrator who has to manage systems, right? And what's the driving thing that's changing our industry? It's automation. We're all trying to build tools that automate our job. We're no longer remoting into desktops, we're now running tools that go and go and automate things, right? And this is where the language Go is excellent because very few of us live in the monoculture. We all have platforms, you might have 20 different operating systems that you're dealing with. Ideally, you only have one, but the reality is most of it has at least two or three different operating systems. Go is great because it allows you to write tools once and run them in multiple platforms. But it's not just that you write the tool once, it's that the language understands that there are differences among the platforms and Go makes it possible to actually accommodate those differences inside the language, inside your engineering process to go into really useful tools. So, yeah, explosion platforms. I mean, everything here, we probably are all running some version of this somewhere in your ecosystem. If you think you're only running one operating system, company-wide, then you at least haven't even looked at your switches, which are probably running something that is slightly a BSD variant or something, you're always guaranteed to be running a multi-platform. So, how hard is it to rebuild Go code for a different language? Well, literally, it's as simple as adding an environment variable. So, if you install the Go compiler, all you have to do is add the environment variable GoOS. So, that Hello World example I gave earlier is built now for Windows and I can run it on Windows and it just works. There's no DLLs, there's no dependencies. You get a single binary that will run on your Windows environment built from your Linux environment that now runs on Windows. All you have to do is provide the GoOS environment variable and go out of the box when you install it. We'll do this. Now, if you're working in Windows, you can do the same thing where you say GoOS Linux and you'll get a Linux executable right out of the box. So, sorry, I'm using someone else's laptop that was generously donated so I don't have my lecture notes so I'm having to make up some of this on the fly. It's mostly not lies, right? So, but the same thing is true for Darwin. If you wanna make an OS 10 executable on your Linux box with the exact same code, all you gotta do is say GoOS equals Darwin and you now have an OS 10 executable right out of your box. This is in your Jenkins environment. If you're doing automated deployment, automated package building, did you know that the code that you write in Go can be deployed to multiple platforms automatically? It's as easy as simply adding an environment variable. NetBSD, why not, right? No reason not to include them. GoOS equals NetBSD. OpenBSD, who here runs OpenBSD? Anyone? Yeah, it is the hardcore, right? But OpenBSD, NetBSD, and guess what, freeBSD too. All of these are included right out of the box and all you have to do is set the environment variable saying what operating system do I wanna build my binary for and you get an executable that you can target and deliver and install on that platform, which means you write code once and you run it anywhere. And remember what, write once, run anywhere? Anyone? Java, yeah, yeah, Java, write once, run nowhere. It's more like it, right? Yeah, yeah, I've spent 20 frickin' years writing Java code and it's never been a good thing. All right, Solaris, who still runs Solaris? Yeah, yeah, the government, is it government or education? Home. Home? Okay, you're just being contrary, like I'm gonna run frickin' Solaris, yeah. Yeah, yeah, usually it's the government people that are still stuck with Solaris, right? But no, all right, whatever you wanna do. Sir, you have a fascinating hobby. Oh, well, there you go, you have friends. They're not government and they're running Solaris? Wow, that's amazing. Usually it's government where Solaris's still showing up. Is it financial? Finance, okay. Yeah, no one chooses to run Solaris anymore. It's usually a legacy, you're bought into it, right? But ultimately the point is, if you've written a useful script, a useful tool, it's this easy to then deliver that tool into that environment. If you're using Chef to deploy a script that's gathering useful information, you can target it to any platform that you want. Oh, Windows, look at this, 32-bit Windows. Right now you can write a program that'll run on Windows 7, right? Someone out here in this audience right now has a coworker that has a Windows 7 environment that is running some mission-critical piece of software that they can't get rid of, but it'd be great if they could bring that into the fold of their automation, right? Okay, who here? Ah, yeah, yeah, I've given this talk in three different cities around the world and there's always someone who's got a Windows 7 environment that's still running production elements that you can't get rid of. You'd love to get rid of it, right? I mean, it's just one of those things. You can run the exact same program, Windows 7, Windows 95. These binaries will run on Windows 95. I don't recommend you do that, right? Don't do that, but you can, right? And it's as simple as saying, in addition to the Go OS environment, there's the Go architecture environment. This is where you set the CPU family. You can write code that runs on Windows on 386, because by default, you get x86 binaries, right? 64-bit binaries, but Go Arch allows you to set a different CPU architecture and that also applies for a variety of different CPUs. So, who here's a sysadmin of some kind? You write scripts, you write utilities, there's always little bits you're writing. Bash, that's what we all have been writing for 25, 35, 45 years, right? It's good. Python was amazing when it came out, but instead of writing those tools in Python, write them in Go, because the big change that's happening now is like, unfortunately, because of the DevOps revolution, we're all now no longer just system administrators. We are software engineers. We don't wanna be, but we are, right? And so, your tools now have a product development lifecycle. You're releasing tools, you're delivering them into production environments, they need to be managed, they need to be version controlled. You need all of those things that go around with software product development, but they're for our tools that just keep the products alive. Go is a great language that allows you to do real software engineering to deliver your tools into the real world. Microservices. Who here is in a world where I have to deal with microservices? We're all, yeah, it's like, oh yeah, it's the fire in which we all burn, right? But microservices, they're all just services. The sad thing is, as administrators, we all know that it's not how many servers you have to deal with, it's how many different kinds of servers you have to deal with. And microservices mean that we now all have 100 million different kinds of services, right? And so, you wanna be able to deliver that automation and solve those problems, but they're running on 20 different platforms. So, there's no such thing as a small system in the real world. Anyone who saw my lightning talk yesterday, like I touched on this briefly, there are no small systems, there are only small engineers, right? The tools that you're developing and you're releasing into your production environments are software engineered systems. We need to treat them like that. We need to unit test them. We need to deliver them in a reliable fashion. Go is a great language that allows you to do that, but it also allows us to do that in a cross-platform fashion. So, yeah, so the whole DevOps thing, good news, all of you system administrators, you're software developers now, right? It's not a career change you wanted, but it's being imposed on you. And, of course, the old style SysOps environment where you just run a technical, a troubleshooting guide or a procedure, you push buttons in response to lights turning on, that's dying, that career, that entire industry is going away. And so, those of you who identify as system administrators, think long and hard about where your career is going and what opportunities available, because automation is going to be taking your jobs, automation is not killing just the careers at McDonald's taking orders. It's killing our career. And you need to be able to think long and hard about what will your career look like in five years and 10 years and what will be the value that you add that warrants the existence of your job in your company. It's all going away. And the ability to write tools that run in lots of environments is one of those things that will keep you employed because you need to expand your skill base. All right, so let's get back to the actual topic of the talk. That was all just the political social rant about this. The US all came to hear about actual running of tools and cross-platform. A lot of us write Python scripts or bash scripts that go and literally just run other things. Like if you write a bash script, you're literally just writing a script that runs another script. And so, of course, Golang has the ability to run other commands. And it's as simple as the OS exec package where you say, oh, go and run this command, take the output of that command and save it in a variable because I want to use it later. And this is something that all of us have done. We've all written scripts that go and run another command and just save the output and put it out. Now, in order to get that code, in order to do cross-platform development, it's not always the exact same command. In this example, the ifconfig command. Everyone knows ifconfig, right? If you're writing a tool that runs under a Chef or a Puppet or an Ansible package that just wants to gather network data about your environment, you'll probably run ifconfig and save that and push it out to some database that you're gonna make use of, right? But ifconfig varies from platform to platform. We can use ifconfig in Linux and it's no problem. So here we have, we replaced date with exec.command ifconfig-a, right? And so, in order to get cross-platform, sorry, in order to get cross-platform development, we need to do a few minor tweaks. Now, this is the ghost syntax to take the list of variables, I'm sorry, the command, the parameters to the exec command and we pack them into an array. So we create an array called cmd here and then we create a function that returns an array of arg0 through argn, right? And we use a little bit of syntactic magic where we say, okay, we wanna pass command zero which is argv0 and then this syntax that says command one colon basically says, and here put the rest of the stuff in that array. So we don't know if the get command function is returning one command or one element or two elements or 25 elements needed to run that program but it gives us the entire command line as individual variables and this is the syntactic magic that says, hey, exec command run ifconfig and then dash a if it's there and then whatever else comes after it, right? Now by moving that into a separate function we can then put, okay, forget command, what do I wanna do? I wanna return an array that says my command is ifconfig dash a and so this is the syntactic magic that says I'm declaring a new array that contains an array of strings and it contains two strings ifconfig and dash a, right? So we now have a function that generates the command that gets the networking information from a Linux or several other Unix-type boxes. Now, in Golang, we move that function into a different file and we call it main underscore Linux. The go compiler knows that files that are named underscore Linux should only be compiled if we're targeting a Linux environment. So that go OS environment variable we looked at earlier, if we say go OS equals Linux, it'll use this version of main underscore Linux, right? And this program, when compiled, will get the IP information about Linux, right? Now on Windows we make a separate file that gets us the command we need for Windows and of course on Windows it's ipconfig slash all, right? That's more or less the moral equivalent of I have config dash a, right? And so we now have two different versions of this and when we compile the program, we've taken the operating system specific information and hidden it in two separate files in a manageable way. We only have the Linux version and we only have the Windows version but the rest of the program which goes and does something useful with that information, it uploads it to a management database, it pushes it out, it does something interesting with that information, that's the same code everywhere and that's part of software engineering, that's the development life cycle where you wanna keep your platform-specific stuff to a small of an area as possible. So we just hide the command that we wanna run inside of a function, we name it underscore platform name, OS name and the go compiler will not compile the main underscore Windows when compiling for Linux and it will not compile the Linux version when compiling for Windows and we magically get a runnable program that runs on both platforms simultaneously. Easy as that. This is all built into the go programming language to run time. If you install go right now on any platform, all this is already there. You don't have to install cross compilers to achieve this capability, it's out of the box. But what if we have BSD, right? It's a Unix-like operating system, right? It mostly behaves, like if you didn't tell someone they were SSH'ing into a BSD box, they might think they're on a Linux box for a while, right? Eventually they'll of course try and do something and everything goes to hell but for a lot of the time they get you get away with fooling someone with a BSD box, the Linux box, right? Well, that go as environment variable, yeah. It's as simple as that. Look, main underscore free BSD, here is how you provide the free BSD version of the exact same information, right? And it will compile that separately. Now, the more conservative among you might notice, wait, I'm repeating the exact same code because there really is no difference between main underscore Linux and main free SB here, right? Yeah. So, turns out go has another mechanism. So in addition to using the file name itself to decide what code to compile for a particular platform, it also has declarations. You can put it a comment at the beginning of the file. So here we say build Linux Darwin net BSD open BSD free BSD. This plus build comment at the top of the file is a build declaration saying, now I called this main underscore Unix like, that name doesn't mean anything. I call it main underscore Bob and it would be the same behavior. But what matters is the fact that I have a build declaration at the top that says for all of these platforms, this is the version of the function that I want you to compile. Completely separately, I have a file called main underscore Windows, which does the stupid I have config slash all, right? But I will get the exact same behavior that I had before, but I didn't have to make a main underscore Linux, main underscore Darwin, main underscore net BSD, et cetera, et cetera, et cetera. I just had to put that declaration there. And now we're doing software engineering. Yeah, now we're playing with fire, right? It's great. So now we're all software engineers doing real software engineering things. We're using declarations and we're creating different versions for different platforms and it all works. Go provides this right out of the box. So if you write a script, you write a utility, you can now target multiple platforms in the semantically appropriate. Now maybe free BSD, whatever you're trying to do is different from everything else. So you pull that out into its own main underscore free BSD, right? There's always gonna be something that's weird. You just pull that out and you only have to make exceptions where exceptions apply. And it's all built into the language. So, yeah, two mechanisms. Whatever you wanna call it, you end the file name in goOS and you will get that code only compiled when you explicitly tell the compiler to target that platform. If you accidentally name a file that ends in an OS that you didn't know about, then it won't get compiled and you'll be confused. But the good news is the number of different target platforms are small. Or you can do the command directors. Now you can also combine them. If you put a comma between them, like this plus build Linux 386, that means only compile this file if both you're asked to target Linux and you're asked to target the 386 CPU on Linux. So commas are an and and then spaces are ors. So in this case, this example is Linux on 386 only and then Darwin on any CPU architecture, right? And this is all provided for you. You don't have to do any magic. This is right out of the box inside of go. Yeah, so environment variable to target the operating system and environment variable CPU architecture. Easy as that, right? And here's the complete list. You can write the exact, you can write hello world and compile it today and target everything from Android ARM to Windows 64 bit. Same hello world code, right? And who doesn't want to run hello world on every one of these fricking platforms, right? I mean, you put that on your resume. Oh yeah, I've written hello world on over 64 systems, right? We're wanted men on 10 systems, right? But the point is you can target open BSD on ARM 64 if you need to and we're all running cross-platform environments. We all love puppet, we all love chef, we all love Ansible, but we often have to write things that augment that and those things are different platform to platform to platform. We now have languages that right out of the box give us the ability to target those different things. So yeah, I mean, this was a quick talk. It's, what time is it? Oh, shit, we're only 20 minutes in. Yeah, you guys can get all the rest of your day back. Yeah, we are all, if you're an administrator running a system, we are now delivering tools. They need a software event lifecycle. They need support, they need everything that happens when you're delivering a product. And so we should use tools that make it easier. I love my bash scripts. I've been using them for 30 years, right? But they're not enough anymore. They're not enough to deal with the variety and the density of environments that we have. And so we should take advantage of modern tools and modern languages to deliver the type of quality environment that lets us go home on time. Let's us get a full night's sleep on the weekend, right? And Golang can provide that. That's it. I mean, this is a quick talk. Any questions? Yeah. Well, CentOS is just Linux. I mean, yes, there's some ABI, there can be some ABI compatibility issues, but I'm sure that you might be able to find an old Linux platform that is so old that the ABI is incompatible, but I haven't found that. I mean, the fact that I can run on Windows 7, I mean, that's pretty far back, you know? So there may be. And I would love it if someone could email me and say, by the way, I tried to run this on CentOS 2 and it didn't work, so yeah. So it compiles the kernel ABI of Linux 2.4 or whatever. Yeah, and it definitely isn't distro specific. It's kernel level and glibc level that really matter and change. Yeah. Oh, glibc doesn't matter. Oh, wow, so this is new. So like, yeah, I thought the glibc interface also mattered, but evidently it doesn't, so that's awesome. They used, yeah, they do, yeah. Well, the whole notion of hermetic binaries, the idea that you statically link everything and you don't rely upon the right SOs, the right packages to be installed, and if you can get the EXE onto the platform, it'll run, has been like central to the go release model, but evidently they've, and yeah, you end up with a 50 megabyte hello world, but evidently that's changed a bit and they're being a bit smarter about what they choose to include, so that's great. But the fact is, as an admin, 50 megs, I couldn't care about losing 50 megs here or there. I mean, it cost me far more to have some junior admin go and manually run a script on one platform once a month if I could spend 50 megs to save that effort, I would spend it, I'd spend 100 megs do that. Yeah, I could name that tune in 200 megs. Yeah, so. Anyway, I mean, that's my message here, is just that for anything you wanna do in Go, anything you wanna do in Python, I'm sorry, anything you wanna do in Bash, anything you wanna do in Python, consider Go. It's a great language, it targets multiple platforms and our careers are changing. We're no longer CIS admins, we're now developers, it's unfortunate, it's the way the world's going, so we need to start exercising those skills in software engineering, release management, and so on, and so it can do anything but good moving forward. Anyway, that's it, oh, another question. Yeah, these slides are available, I'll tweet out a link to them, I mean, there's not a lot in this slide, Go OS and Go Archer, the only two takeaways from this talk, right? I mean, unless you need the source to Hello World, I'll show it to you here, and the cat, yeah. Yeah, here's the secret source to Hello World, right? But yeah, I mean, yeah, so Go OS and Go Archer, nothing here is really new information, it's easy to find, I'm happy to, yeah, I'll tweet a link to the slides and whatnot, but other than the fact that you can now write Hello World for about 40 different platforms without having to do anything other than recompile, but you don't have to install cross-compilers, I mean, I remember the first time I tried to use GCC to compile ARM code on an x86 box because I needed to deal with a router that was only able, it was an ARM CPU that ran a variant of Linux, and that was, it was like, it was a nightmare, and now it's as simple as declaring an environment variable when I run the compiler, you know? Let's leverage these things, let's get out of the world of Bash and Python, which, yeah, you can write a Python script, I've been in environments where we had portable Python scripts that would run on Sun and Red Hat and on the internal variant of CentOS that we used and on Windows and on Solaris, but the amount of code that was platform-specific was miles long and it was always out of date, and so there was the one platform that it always worked on, and then the other platforms only, it only worked on it if you had a build from the last time that someone cared to look at it, all right, whereas Go actually gives a set of tooling and an environment where you can keep all that up to date and you minimize the amount of platform-specific garbage, all right, yeah. Excellent question, can you mix languages? Go does have a way to basically call out to anything else written in C. It's not commonly used because culturally, the Go community, this is common in Python where there are lots of Python libraries that only work if you're on Linux and you have the underlying SOs installed for MySQL or something like that. Culturally, the Go community sees that as a poor implementation. If all you're doing is wrapping a library, which you can do, you can call out to a C library or a shared object, there are mechanisms to do it, but culturally, the community sees that as an inferior implementation, and so if you do have access to a library, the great news is OddsR is cross-platform because it's been re-implemented in Go by the library maintainer in a way that will now compile on all of your target platforms. So yes, you can compile, you can wrap platform libraries in Go calls that allow you to call into it, but also the good news is most of the libraries that you might be using from the open source community are re-implementations, not just thin wrappers around those libraries, okay? So does Go offer any opinion around variance of Linux system D versus non-system D supported environments and so on? Go doesn't care. I mean, there isn't any, there's no community bias toward one platform or the other and there's no explicit support. So if you have a platform that isn't in that list of Linux, I mean, it's very broad categorizations, all Linux's are considered to be Linux, and so if you do have a variance that are within the ecosystem of Linux, you're gonna have to deal with that unfortunately on your own, where you have to check, okay, am I running on a system that uses this way or that way? But at least that code's not being tried to be delivered on a Windows box that's completely irrelevant. So unfortunately, yeah, it is a sad thing that we're getting so much fragmentation inside the Linux community about how certain core things are done. I mean, system D is, it, oh, yeah, wrong talk, yeah. Over beers I can tell you my stories about system D. Yeah, no, it's its own thing, but yeah, we are getting fragmentation and unfortunately we're getting some people who are taking very hard lines. But as I said, these are differences, but they're differences within our community that we're able to reach across boundaries and ultimately, like I said, the platform wars have died and that's a good thing. I'm so happy that I'm not living in the world that I was living in before where you couldn't even have a cogent conversation with someone if they had a laptop that was running the wrong operating system. Ironically, I think it might have been Apple, that Apple's injection, I mean, I'm looking around the room and I see nothing but Apple computers throughout the room. Like, Unix guys use Apple's as their laptop, right? And what do you look when you look over someone's shoulder? They got 20 SSH sessions open to Linux boxes, right? On their Mac, right? And it's, I think that was one of the things that kind of, it kind of broke the back of that platform and transigence because they realized that wait, I can't say that Linux is the only operating system when I'm sitting here on a Mac. SSH to do a bunch of Linux boxes, so I'm very happy that we've evolved beyond that and we've all seen that the things that make us, that bring us together are stronger than the things that drive us apart, so. I mean, that went way beyond, we're talking about what you're talking about, but. I mean, we got like, still we got like 25 minutes here and I got nothing else to talk about, so. Anyway, yeah, definitely wander off to, yeah. Favorite libraries, oh, see that, that's a hard question because like I, just last week I needed to go and write a tool that spoke SMTP and syslog using go to then pipe that data in another system and I went out and looked and there were like nine different implementations and like anything you wanna do and go, it's there. Like someone's written it, goes now, been out for six years, something like that. There, I mean, I thought that when it came down to syslog, which a lot of people, who here deals with syslog, right? Yeah, I mean, there are three different versions of the protocol. There's the BSD protocol, the original protocol, there's the RFC 20 something something and the RFC 34 something something protocol or something like that, right? There are actually three different versions of the protocol and I didn't realize that already years ago, and these libraries are now like four years old, they were written and they're done, someone's already implemented all of them because sysadmins are using go to do real work and I now, by importing two libraries and writing nine lines of code, more or less, I had a fully functioning reflector that would ingest SMTP traps and syslog from a couple of devices that I had to basically do that. I just needed a tool that could receive that and bounce it off to another system and it was already there. Admins are using go like already, so this infrastructure stuff, most of it's already been written, it's amazing. And that same, that binary, I wrote it on a Linux box and it was being delivered to a Windows machine. It was replacing some .NET abomination which was, it was an abomination, right? And it took nine, 10 lines of code and right away it ended up, I ended up with less than 100 megabyte binary that used a fraction, basically unmeasurable zero CPU resources to do its job whereas the other was consuming 25% CPU because of the framework and all that other stuff that went along with it. Go is an amazing language, it's super efficient and the people who write libraries for it, you go on GitHub and there are so many things that are written in go and it makes life easy. Yeah, scripts rewritten in go that are more performant than others. I don't have myself an example. I spent a bunch of years working for a company where go was a major priority, right? And I would see pull requests essentially from groups where they said, oh, I rewrote this Python utility in go and it consisted of 4,000 deleted lines of Python and 200 added lines of go and that was the pull request because I, and so while I have not done that myself where I've rewritten major tools because basically I use go for all new tools that I write, I have seen in practice that yes, you can delete thousands of lines of Python or Bash and replace it with a couple hundred lines of go and I've seen that happen over and over and over again. Ironically, it wasn't until I left Google and started working for Microsoft that I started writing go. I spent years trying to utilize go at Google and I just didn't, like the inflection of what I need to do with my career didn't match. I spent most of my time at Google writing, C++ and Java and it was only when I left and went to Microsoft where now I was in environment where the deployment target was mostly Windows based servers and I was like, I don't wanna write .NET code and I'm writing go code and it allows me to live and work in the environment that I'm most efficient in, which is Windows target the Windows. Live and work in Linux target Windows and it worked but more importantly, my colleagues who are living and working in Windows are able to work with my code. We're able to collaborate and develop in parallel because for them go on Windows is no different than me go on Linux and we're targeting both Linux and Windows environments and it just works, you know? Well, Go definitely has capabilities that didn't exist traditionally in languages like Python and so on. The whole notion of go routines and how you connect things up with channels, I mean it is, I've oversimplified things for the person I talk. The fact is if you're gonna write a large tool in Go, you might wanna learn things like go routines and channels and once you learn how to do that stuff and you write code that uses go routines and channels, it makes your life so much easier but it's a different way of thinking. I mean, I've struggled for years with getting my head around functional programming, right? It's functional programming languages are weird. Who here's a Haskell guy, anyone? Yeah, they're super powerful but you have to think differently when working in that world. Now Go lets you do things in a procedural manner and so you can write your Go code like you write your Python code like you write your bash code but if you choose to take advantage of the more advanced features, you can end up with doing in five lines what someone else would do in 50 lines. So yeah, there are things that you can take advantage of in Go that make your life easier but you first have to wrap your head around thinking that way. All right, thank you so much. I mean, yeah, I appreciate all of you sticking around. It's almost the end of the day. We've got one more talk to go. Everyone know what talk they're gonna see for the last session? Yeah? Not sure, not sure, all right. There's a JSON talk? Something JSON? It might be about JSON. Web tokens? Token, token is not the same as token. Anyway, thank you. This has been fun. Yeah, I'm going to get a beer. I'm gonna stay for the JSON talk and then I'm gonna get a beer. I am not getting beer for everybody at the talk. I'm with the C Libraries. When you do... Hi, wow, that's loud. It's 4.30, I'm gonna give people another couple of minutes just because things are, you know, it's the end of the day and I'm not gonna use up this whole talk slot. So a couple more minutes, we'll start going. If you're not here for the JSON web token talk, you're in the wrong room. Okay, let's get going. So hi, welcome to JSON web tokens. We'll improve your life. I'm John, go by Gene Hack, Most Places Online, Twitter, GitHub, IRC. And in my day job, I'm the vice president for technology at an IT consulting firm called Infinity Interactive. I used to do a lot of cool stuff and then I got promoted into management and now I basically go to meetings and occasionally cosplay Brian Lumberg from Office Space, the coffee cup, what's happening. But I do occasionally get to work on a coding project and this talk was born out of a coding project, a couple of projects that I got to work on that use JSON web tokens and I thought they were pretty cool so I decided right to talk about them. This is my dog, Sammy. Sammy works from this bed under my desk and she helps me out with my coding projects. So who's heard of JSON web tokens? Okay, like half the audience. Who's used JSON web tokens? About half the audience. Hopefully I'm not gonna say anything wrong that you'll feel the need to correct me on. So what is a JSON web token or a JOT which is the official pronunciation of the abbreviation? So you might try to Google JSON web tokens and if you do, you will end up on this website, jwt.io which is the official website for the project which will hopefully tell you that JSON web tokens are an open industry standard RFC 7519 method representing claims securely between two parties. Sammy didn't really get a whole lot out of that description. This is also when I should mention that Sammy suffers from an unfortunate disorder called RSF or resting stone to face. But I persevered. I went and looked up RFC 1719 which is titled JSON web token or JWT and this is where you will be told that the official pronunciation for JWT is JOT. Reading this the first time was kind of confusing because there's a bunch of stuff that it refers to that's not actually in the RFC and it took me a little bit and it turns out that you don't only need to read RFC 1719. You also need to read RFC 1715, 1617, 18 and my personal favorite RFC 7520 examples of protecting content using JSON object signing and encryption or Jose. Yes, way. Sammy found the RFC content to be a little bit dry. She kind of really just likes to focus on the code. But I persevered and I read through all this stuff and so I can tell you the JSON web tokens are kind of sort of a lightweight alternative to cookies that will also work with command line apps or mobile apps or even desktop apps. They can also be used as an authorization or access control mechanism, kind of like OAuth but without you losing the will to live as you try to implement it. And they're also cross domain friendly. They're made up out of stuff you probably already know and use. So they're just plain old JSON objects or pojos. I'm gonna say pojo a lot in this talk. And then those are stringified and coded and cryptographically signed and then transmitted back and forth over HTTP or HTTPS. So what does a JSON web token look like? It's a dot to limited string. It's got three parts, a header, a payload and a signature. And those three parts are just separated by dots. So down here at the bottom, you see XXX is the header, the Y's are the payload and the Z is a signature. So let's look at each one of these parts in a little bit more detail. So the header, like I said, it's just a plain old JSON object. It's stringified and then base 64 encoded. And it typically contains metadata such as the type of token. In this case, this is in the TYP key. This is a JSON web token. There are other kinds. I'm not gonna talk too much about. And it also includes the data about what algorithm is being used to sign the key. In this case, Hmax SHA-256. And the abbreviations for all of these different things are actually in 75.19 or on JWT.io. The payload is just another stringified base 64 encoded pojo and it contains what the JOT documentation calls claims. This is really just the key value data that's in the pojo. A claim is just a key and a value. There are three different types of keys that are used, reserved, public and private. Reserved keys are those that are in the RFC. They typically have three letter names and these are for things that everybody uses, stuff like when the token was issued, when it expires. There's also a provision for public keys. These are designed to be registered with IANA and you would do this if you were making a JSON web token protocol that you were going to expect to be very widely used. It's probably never gonna come up. And then there are private keys, which is your data, the stuff you care about. And you can put anything in there. It's just a plain old JavaScript JSON object. And then finally we have the signature, which is the header plus the payload, which is then run through some sort of HMAC algorithm along with a secret that you have and that generates a signature. Generally, like I said, the signing algorithm is in the ALG key in the header. So I'm gonna be showing a fair amount of code in this talk, maybe a bit too much code, but I really wanted to drive home how simple and elegant the JWT system and algorithms are and showing how they actually work on a code bubble is I think the best way to get this across. These are not complicated. They're really pretty simple. It's elegant is the word that I keep coming back to. So in real practice, for a lot of the code that I'm gonna show you, you would never write this code. This code is in a library somewhere that you should find and use, but it's also useful to look at what's actually going on so that you understand this is not really rocket science. For each code sample, I'm gonna show you the whole chunk of code at once. At first, it is going to be very tiny and those of you in the back are gonna be like, dude, but don't worry, we're gonna step through each in like three or four line blocks and you'll be able to see it. But I do think, just seeing, it's not really that much code in the grand scheme of things. So here is JavaScript code to generate a JSON web token. That's about 20 lines, only the last four are actually doing the work. The rest of it is setup code. So first we have a helper function to base64 encode a pojo and it just takes a JSON object, stringifies it, converts it to base64 and returns it. Very simple. We have another helper function that takes a string and a secret and then generates an hmax SHA-256 object, uses the secret to initialize it, sticks the string into it and gets the signature digest out. Again, very simple. We have here the actual data, we're gonna put into our JWT and the header and the payload are just the exact same data I had on the previous slides and then we have a secret, can just be anything, it just needs to be kept. Secret, just right there in the name. And then this is how you actually generate the signature. We're gonna use our two helper functions. We're gonna base64 encode the header, base64 encode the payload, take those two things, concatenate them together with a dot in the middle of them and generate an hmax signature from that combined string and then we're gonna stick all three of those things together, header, payload, signature, with dots in between. And so if you take this code and actually run it, you will generate hand roll about artisanal JSON web tokens that you can print out and it just looks like that. I have introduced line breaks after the dots but that's a valid JSON web token. The key part of JSON web tokens is because the signature is based on the combination of the header and the payload, any modification of the header and the payload invalidates the signature and validates the token. So I can generate this, I can give it to you, consumer of my API or whatever, require you to give it back to me as part of using my API and you can't change it. If you change it, it's gonna invalidate the signature. You can't generate a new signature because you don't have the secret, I have the secret. So that's pretty much, you can leave now. That's like we're done. That's the key, right? One other useful thing you will find on the jwt.io website is this little bit up in the header, it's probably too small to read, that says debugger, which is a nice web interface that lets you go backwards. It's a nice web interface that lets you paste in a JSON web token and it'll pull it back apart for you. So here, I've pasted in the JSON web token we just generated. You have to take my word for it that that's the same string. And if you're close enough to read that, you can see that it's pulling back out the same data that we put in, right? This is good. This is actually really super useful when you first start using JSON web tokens, particularly if you do some of the more complicated stuff I'm gonna talk about later. GWT also has, and these are all listed on the website, it has insane library support. There are JSON web token libraries for .NET, Python, Node, Java, JavaScript, Ruby, Perl, Go, PHP, Haskell, Ruby, Lewis, Scala, Clojure, Objective-C, Swift, and Delphi. Anybody in the room using Delphi? One guy. Generally speaking, in my experience, if you've got a technology that has Delphi support, it probably supports whatever platform you're using. There are no COBOL libraries yet. I had somebody ask me that once during this talk. I had to go look. There are frequently, for most of these platforms, there's more than one library. I think there's a 4chan77 library on there. So at this point, Sammy perked back up. Now that we're past the RFC reading stage, she's seen sort of how simple and elegant GWTs were. She started asking, how do I actually use these? So in this figure that I blatantly stole from JWT.io, you can see how you would use JSON web tokens in a kind of a basic standard authentication authorization flow. We have the client here on the left side, server on the right side, and you're gonna start out and you're gonna post to your login endpoint. In this particular example, user login. You're gonna include your username and password, and the API is gonna get that request. Authenticate the user, generate a JSON web token containing whatever claims you need, and send it back as part of the response. And then at that point, the client needs to take that token, and any subsequent requests to the API include the token with them. So every request to the API is gonna pull that token out, validate it, use the data in the token to help generate the response and send it back. So not a complicated flow. Then the important thing to note here is that blue box on the left-hand side, that doesn't have to be a web browser. It can be, it can be JavaScript code running in a web browser, but it can be a CLI script, it could be a mobile app, it could be a desktop app. It's just standard HTTP stuff. Something I'm going to emphasize several times during this talk is the header and the payload are not encrypted, right? They contain serialized data that is completely trivially reversible, right? If somebody has a JSON web token, they can see what's in the header, they can see what's in the payload. You don't want to put somebody's social security number in there, bad idea, right? But something like a session ID, something that would normally already be in a cookie, whatever, right? No harm, no foul. You are responsible for controlling expiration, token refresh, all that good stuff. I have seen some APIs, and there's no real rules for that. One of the simultaneously great and sometimes frustrating things about the JWTRC is they don't specify a lot of implementation detail about how these things are used. So I've seen some APIs where they send you a fresh different token along with every API response, and they expect you to constantly just be using a new token all the time. Or you can have a refresh endpoint that you implement and tell the client, hey, when you're about to expire that token, use your current token to get a new one. The other important thing, and I'm gonna mention a couple of times because it's one of the cool parts, is unlike a cookie, this is not subject to any browser control, same origin policies. This is not subject to any cores stuff. You can get a JSON web token from site A and turn around and give that JSON web token to site B, and as long as those two sites have made arrangements to share the secret, to validate the token, things work just fine. So this is an extremely lightweight way to do single sign on like things, which is pretty cool. Who's worked with SAML? Who liked working with SAML? All right, yeah, so there was one hand in the back, like, god damn man, I'm sorry, I'll buy you a beer later, I wanna hear that story. So how do you actually throw these tokens around? Again, the RFCs don't really specify how that works. You can do whatever you want. You can put it in the URL and a get request, just in line. You can put it in the body of a post, or a system that I quite like is there is a header that's in the HTTP spec called authorization, various schemes that you can use it for. One of them is the bearer scheme, and so you just have a header that says authorization, bearer, and then your token. You include that as part of generating your HTTP request. All right, so Sammy, as you're probably detected by now, is not really big on theory. She very much just wants to see some actual implementation. So this is the code, this is a chunk of node code for generating a token as part of an authentication workflow. Again, that's not a lot of code, that's like 20 lines of code. I pulled this out of an express app. So first we're gonna define a root for the user login endpoint. We're gonna point that at the user login function. We're gonna import a JWT library. This is an in-house, a very lightweight wrapper we use around the JSON web token library that you can get on NPM. I highly recommend JSON web token, it works really well. And then the first thing we're gonna do is make sure that we got sent an email and a password, because that's what we used to log in. And if we didn't get those things as part of the request, we're gonna return a 400 error. If we did get those things, we're gonna use the email to pull the user information out of the database. Then we're gonna instantiate a claims object. We're gonna try to validate the password. And if the password validates, we'll stick the user ID in the claims token. Otherwise, if it doesn't validate, well, you just fail to log in, here's your 401. Have a nice life. If we did make it past that, we need to sign that claim using the JSON web token library. And our secret in this particular code base is just inside that particular part of, it gets read from a config file inside that part of code. And then we send it back in a special X header. You can name this whatever you want, right? It's just the client has to know it's gonna come back in this header. And then we return a 200. Okay, cool, so that's how you generate one. How do you handle subsequent requests where you need to validate it? And again, because this is express, the easiest way to do this is with a middleware. We can just load up a middleware in our express app. That's gonna get a chance to inspect every request that comes through, and we can make sure that it has a JSON web token on it. So we're gonna load up that library again. We're gonna instantiate a middleware, and we're gonna take the request object and put an empty JWT key in it, just to have a place to hold stuff. Sorry, this is a little bit too much code for this slide. The important part here is right in the middle, we're calling JWT.verify and giving it the token. And if that verifies the token, it'll return successfully, and we'll return that value, and it'll move on to the next step in the promise that I'll show you here in a minute. If it doesn't, it's gonna throw an exception, which we're gonna immediately re-throw. Otherwise, if we didn't even get an authorization header in the request, we'll throw an exception for that too. And I will post these slides online later and tweet it, so that if you wanna look at this code in more depth, that will be possible. If the promise successfully receives, we call the then, we get the payload passed in, which in this case, the library is just returning the payload object, decoded and ready to go. We stick that into the JWT slot on our request object, and we call the next function in our middleware chain, and we move on. At this point, we may go to the endpoint, we may go to some other middleware, but we've gotten the JSON web token, we know it's correct and proper, and we've decoded the payload. Otherwise, if there was an error thrown, we have this terminal error handler, we need to make sure that this isn't a request to log in. If you're trying to log in, obviously, you're not gonna have a JSON web token, and we need to let you through the door anyway. Otherwise, here's your 401, have a nice life. So at this point, Sam was like, okay, this is kinda cool. Like, I can see how this would be useful, I'll use this in some projects. But she was wondering if there was anything else JSON web tokens could be used for. This is the point where I, this is the thing that actually happened that inspired me to write this talk, because I thought this particular usage that I'm gonna talk about was actually really cool, and it is a solution for a problem that I feel like I've run into multiple times in the 10 or 15 years I've been getting paid to write software. So you're gonna write a new thing, you're gonna put it on the internet, and you have two choices, basically, or you used to have two choices, 10 years ago you had two choices. You can put no access control on it at all, you can just put it on the internet. The MongoDB pattern, probably not the best idea. Or you can implement a full user authentication authorization system, and then a couple of weeks later you can implement admin screens for it, because you get tired of directly doing SQL queries to deal with users, and it just turns into a horrible thing. Or you could use OAuth. I've never had a good experience implementing OAuth, server-side or client-side. Who's used OAuth, who liked it? Few people, okay, you can join the beer party later. So it would be nice if there was some middle ground, I feel, between a completely open door and a bank vault. I want a screen door for my APIs, right? I want to be able to set them up so that there's an API, and I don't want to just let anybody in, but I don't want people to have to authenticate either. And it turns out that there's a way to use JSON web tokens to accomplish this. So instead of using a symmetric algorithm to generate your signature, you can use an RSA public-private key pair for generating the signature in the JSON web token. And you generate the signature with the private half and you validate it with the public half, but the super cool thing is, there's a special defined header so that you can put the public half into the header of the JSON web token itself. Okay, so this is called JWK, JSON web key. It's a special format for defining, for serializing out the RSA key. And what this means is you can set things up so that your API client can generate a JSON web token all by themselves without hitting an endpoint on your API, without authenticating to your API. They can generate a JSON web token. You'll be able to tell it's from a valid user of the API and they'll be able to use the API. So to make this work, we have to give our authorized clients a key pair. We need to know the fingerprint of the public half of that key pair. We don't actually have to give them the key pair. We can let them generate the key for themselves. We just need the fingerprint of the public half. And we'll see why here in a minute. On the client side, they generate a JWT. They sign it with the private key. They include the public key in the JWK slot in the header. You need to make sure if you're going down this road that you have issued out an expiration, time claims in there as well. I'll explain why here in a minute. And then once you have this JSON web token, you just send it in with your API request. On the API side, we get the token. We pull the public key out. We validate the signature on the token using that public key. We generate the fingerprint of the token and we make sure it's a token we know about. It's in our whitelist. So at that point, we know that the signature on the token had to be produced with the private half of this key pair because otherwise it wouldn't validate. And we know that we have a whitelist fingerprint for the public half, so therefore, this token came from somebody who's authorized to use the API and we can continue processing their request. You need to look at the issued at time and make sure it's not in the future. You need to look at the expires time and make sure it's not in the past, obviously. Ideally, you will find a library that just does this for you. And again, nothing is encrypted, so you don't want to put anything sensitive in the payload or the header. Here's some client-side code for this. It's written in Perl. That's because this is what this project happened to be in. And again, that's not very much code. We're gonna start out and load up a couple of libraries to deal with cryptography stuff. We're gonna load up an HTTP request library and then we're gonna read in the private and public keys. Practically speaking, you probably shouldn't store these in the same directory as your code. You should probably have them in some sort of secret vault service. Then we have this single call to this encode JWT method from the crypt JWT library. We're gonna use the RSA 512 algorithm. We're gonna include some extra headers, including this JSON web key header that is coming from the public key. We're gonna use the private key to sign it and we're going to include in the payload an IAT claim that's the current time. And then one of the nice features of this library is it lets you say, this token that I'm about to generate has a relative expiration time. This is gonna expire a half an hour after it's issued. And it'll figure out the math for you. Both of those values should be epic seconds. And then we just make a new HTTP request, sending this to wherever, putting it in the authorization header. So that's pretty simple. The critical bit here is the extra headers part where we take that public key and export it in the JWK format. I spent about six hours writing this project. It's a very simple API. About two hours of it was figuring out that that needed to be in JWK format and not PEM. That's not really clearly documented anywhere. Older RSA libraries don't know from JWK format, but these RFCs are a couple years old. You should be able to find one for your platform that does this. On the API side, again, not a whole lot of code to handle processing this token. We're gonna load up those same libraries again. This API was written using a micro web framework for Pearl called Dancer. That's very similar to Sinatra, if you're familiar with that. We're gonna take and pull the authorization request header. It is Pearl, so I'm required by Union Rules to use one regular expression minimum. So we're gonna regex the bearer token out of the authorization header, and if we can't find it there, we're gonna return a 401. Then we're going to try to decode it. We're gonna do this inside an exception handler. We're gonna use the decode JWT method from that Crips JWT library again, and we're gonna give it the token. We're gonna ask it to decode the header. We're gonna tell it that only the RS512 algorithm is acceptable, and we're gonna ask it to verify the issued at and the expired claims for us. So this will make sure that the token wasn't issued in the future. This will make sure that the token hasn't already expired. If any of those things fails, so if the token doesn't validate if the issued at or expired claims aren't there, if it's not the right algorithm, it'll throw an exception. I don't have to even catch that exception, because if it throws the exception, there won't be any values in the header and payload variables, so I just checked to see. Did I get a header and payload? If I didn't, here's your 401. Here's a slide that tells you everything I just said. So all of this stuff is happening inside the library. I don't have to deal with it, and that to me is sort of the mark of a successful coding platform is stuff that I don't have to deal with. We also have to do a few more checks. We specify in our API documentation that tokens can only be issued that are good for an hour, right? So we need to check that. We also need to make sure that this isn't some random RSA key pair. I'll explain that here in a minute. So what we're doing here in this first line is if the expiration time is more than an hour after the time the token was issued, we throw a 401, because again our API documentation says don't issue tokens that live for more than an hour. The threat model with the screen door approach to the internet is if somebody manages to get a token, somehow they sniff it off the wire, whatever, somebody writes it down and puts it on a USB key, they'll be able to use your API until that token expires. Now this API for this particular project, I don't care, if you manage to steal a token and get to 47 minutes of access to the API, more power to you, right? You're not gonna be able to generate a new token after that. So we have to check that ourselves. We also need to make sure, so everything up to this point, right up to this point in the code, you could get to here with just some random RSA key pair that you generated yourself that I've never seen before. There is no check up to that point that the person who generated the token is somebody I know about. That check happens when you make sure that the fingerprint of the public key is on your white list. At that point you know, oh, this came from a good key pair. So that's what we're doing here at the end is just pulling that key back out of the header, generating its thumbprint, and making sure that's on our white list, right? So that's it. We know the public key was in the header. We know by its fingerprint that it's an allowed public key. We know the key validated, so it must have been generated with the private half of that public key. And if somebody has the private key, by definition they're an authorized user of the API. So we're good to go. This does of course depend on the client keeping the private key actually private. So for example, if your client was implementing a single page web app that was going to hit this API, and they included the private key in the big blob of JavaScript that they were shipping out to the browser, that's not really private at that point anymore. Not that that would ever happen. But the good news is that the revocation protocol for this is very simple. You go into the white list, you delete the fingerprint of the leaked key, you're done. There are other things that you can do with JSON WebToken that are more advanced than these two examples that I have given. There are ways to, the defined ways to encrypt the payload so that you can ship around sensitive information. I'm not gonna talk about that. There is an RFC for JWE that you should look at if you're interested in that. And it's also possible to nest JSON WebToken that's specifically spelled out in a very detailed and perhaps not overly exciting part of the RFC where basically you generated JSON WebToken and then you stick that in the payload of a different JSON WebToken. See those RFCs if you're interested in those things. In conclusion, I think JWT solves some really common problems that we probably all have as API developers and users. I think they solve them in a pretty elegant way that's much simpler and easier to understand than alternatives that do the same thing. I think that's pretty damn cool. And I think you should think about using them if you're not already. I'd like to thank the JWT.IO people and offo.com who is the people behind JWT. I am not affiliated with them in any way. I just think they develop something cool. I'd like to thank the organizers. This is the last session of the conference. So round of applause. This is the first time I've been to scale and it's a large impressive operation. I've helped put on smaller conferences and I can't even imagine how much work this is to do successfully and it's been pretty fun. And I'd like to thank you for sticking it out and actually coming to the last slot. I've pretty much been convinced since I saw I was in this slot that I was gonna have two people in my talk. So I'm glad there are more than two people here. I also need to thank my company because they pay me to work on this crap and they pay to send me here and they give me time to write these talks and we're pretty cool. We do stuff. If you need stuff done, talk to me and I'm happy to take any questions. Or we could all just go home. So JWT says there are two different algorithms to use. What are the differences between the two? In the validator you're looking at. So one of them is the HMAC SHA-256, one that I talked about first where you have a single secret and the other one is the RSA key pair one. And if you toggle that to the RSA key pair one, you won't be able to validate the token online, I think. I think the debugger really only fully supports the HS-256 algorithm. What we've done practically speaking is we don't worry about token invalidation at all. We just use the expiration time value and the client code is written. So the overall expiration time is picked as, sorry, let me back up a step. So we're writing this against the particular security policy and the security policy says sessions have a 60 minute lifetime, right? So when we generate a token, the expires time is 3,600 seconds later than the issued at time. The client code is written so that if at any point it sees a token or the TTL, the time to live, the remaining time on the token is less than half of the lifetime of the token, there's a refresh endpoint. And that refresh endpoint kind of works like a TKT and Kerberos, right? If you have a token, you can get a new token from that endpoint. So the client code just has a routine that fires asynchronously that just says here's my old about to die token and gets a new one. And then other than that, we don't track. We log the token in the database but it's just informational, like we don't invalidate them in any way, they just expire. Does that answer your question? If you're a bad guy and you've already gotten the token, we already lost in that particular instance. Because at that point, if you've gotten the token, you've already gotten everything that's in there and yeah, we're screwed. Right, have we thought about having the clients into secret so that we're sure there's not somebody, man in the middle, in the token request? No, I haven't done that. That might be, that sounds familiar and that might be one of the use cases in the RFCs for the nested JSON web tokens where you can basically, you can include an RSA encrypted web token in a signed web token but no, I haven't done any of that. I've only been using this stuff for less than six months. I just thought it was really cool and it doesn't seem to have gotten as much traction as I had hoped that it would but half the people in here use it so maybe I'm just wrong. Any other questions? Yeah, sure. So how does knowing the fingerprint help you know that the API user is legitimate? Okay, so we get the token, we validate the token. So here's the extra checks. So, up until this point, right, all that we know is there was a key pair out there somewhere and somebody took the private half and signed a JSON web token that included the public half because the public half that we're using to validate that signature we pulled out of the JSON web token we got. So that could have been just any old random RSA key pair. I need to make sure that the RSA key pair that's being used is one that somebody has told me, like, hey, we're gonna use this key pair. And the way that I do that is the fingerprint of the public key. I record that, right? And then when I pull the public key out, I just generate its fingerprint and make sure that it's on the list of allowed keys. Does that make sense? The client can generate the public private key, they just need to tell you the fingerprint. Yeah, yes, exactly. Questions? Thanks again for sticking around. I really appreciate it. I hope everybody had a good conference. I hope to see you next year. And thank you. Oh, and like I said, Jean Hack is my Twitter handle. At some point within the next 24 hours, I will put these on a slide sharing site and tweet about it. And I'll scale 15x tag it.