Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1012 lines (506 sloc) 82.5 KB

Mat Ryer: [crowd applause] Thank you, hello! That was very generous of you, giving that to just me. I really appreciate that.

Mark Bates: Yeah, Mat's gonna edit that in over all his bad jokes later...

Mat Ryer: That's my text message sound from now on. Well, welcome to a very special episode of Go Time. And it's not just a podcast, this is also real-life as well, for those of us in this room... It's a pre-conference social for one of the best Go conferences in the world, GopherCon UK, so we've got that coming up. [crowd cheering]

This is also a part of the monthly meetup that is London Gophers, which we'll talk about a little more later as well, which is one of the best Go meetups in the world... So let's give it up for them! [crowd applause]

Mark Bates: ...if not, the best in London. I think we can agree on that.

Mat Ryer: And also, the other voice you can hear is one of the best Mark Bates in the world. [laughter] It's Mark Bates.

Mark Bates: Yeah, that's right. That's me. Thank you, Matthew Ryer. I like to applaud myself, because most people don't... So thank you for having me. We're very excited. As you can tell, this is a very different Go Time than we normally do. We're in front of an audience, like Mat said. Mat's wearing trousers, which--

Mat Ryer: That's actually what I'm the most nervous about. It's not having the live audience.

Mark Bates: So we'll see if that in any way impacts Mat's hosting abilities over the next hour.

Mat Ryer: They can't get worse.

Mark Bates: No, they really can't, honestly... We've got such a wonderful panel of people that we wanna talk to, so we're just gonna obviously introduce them. I'm gonna start with Liz Rice here. Liz, tell us a little bit about yourself.

Liz Rice: Hi! Thank you very much, Mark. My name is Liz Rice, I run open source engineering at a company called Aqua Security, where we write lots of code in Go. [crowd applause]

Mat Ryer: A round of applause! We can't do a round of applause on the podcast normally. This is brilliant.

Mark Bates: Yeah. Well, we can, it's just very weak. [laughter] It's usually just Mat, he tells a joke and he goes [clapping].

Liz Rice: To be fair, there are people on Slack clapping with you.

Mark Bates: Yeah, that is true. Okay then.

Mat Ryer: That's true. Sometimes they miss all the fingers off on the emoji when they clap to me though.

Mark Bates: Yeah, just the one. I've seen that, too.

Mat Ryer: Weird. Really strange kind of wave.

Mark Bates: Yeah, I get that emoji a lot. It's weird. It's one-off, I think.

Mat Ryer: I'm gonna introduce another one of our panelists. I haven't made his name up; genuinely, this is his real name... It's Gautam Rege. Just imagine...! [crowd applause]

Mark Bates: Gautam, would you like to introduce yourself?

Gautam Rege: Well, if you want to push it to the limits - you know, I'm on GoTime... My name is Gautam... It's pretty close by.

Mat Ryer: Very good.

Gautam Rege: [00:04:04.13] That's why they decided to get me on the panel. [laughter]

Mark Bates: What we really like doing is giving Mat -- we tell them one pronunciation of somebody's name... Schleslinger, Boursiquot, Gautam. And we just like to see what he does with it on stage. It's quite fun.

Mat Ryer: Yeah. I'm much better in text. [laughter]

Mark Bates: Gautam, tell us about yourself.

Gautam Rege: Well, I have my own software company back home in India. It's called Josh Software, and Josh in my mother tongue means enthusiasm and passion...

Mark Bates: Great.

Gautam Rege: So that's what we do - we do a lot of consulting in Go and Ruby. These are the only two languages we've been doing for the last 12 years. So that's me.

Mark Bates: You don't happen to also maybe run a Go conference in India, do you?

Gautam Rege: Yeah, actually I'm the organizer for GopherCon India.

Mark Bates: Oh, there you go then. So if you wanna go to India...

Gautam Rege: And just to let you all know, the next time it's in Goa, which is a residential conference; that means all the attendees and speakers -- we book the entire hotel, and everybody stays together. So if anyone's interested in coming to Goa, which is like the Florida of India...

Mark Bates: So it's hotter than the rest of India.

Gautam Rege: The problem is a lot of people register for the conference, but don't attend the conference because they're at the beach. [laughter]

Liz Rice: It's really on-brand, the place name though... Goa.

Gautam Rege: Absolutely. Go in Goa.

Mark Bates: Yeah, love it.

Mat Ryer: They couldn't have it in a place called Javarra...

Mark Bates: You know there's an actual place called Java, that they could have just actually used... [laughter]

Mat Ryer: I'm much better in text... [laughter]

Mark Bates: Again, it's that single-finger emoji... And in the middle here we have Kat. Kat, say hi.

Kat Zień: Hello, I'm Kat. I work for Monzo, which is a company here in London, and I'm also one of the co-organizers of London Gophers, together with Dom and Paul and Antonio. We're all wearing yellow T-shirts tonight, so if you wanna chat to us, by all means, come up to us and say hello.

A big thanks to GopherCon UK and GoTime for doing this together. This is awesome. And as always, thanks to our sponsors, Monzo, Bud, and Martin from Vistas, without whom we wouldn't be able to run our meetup. It's a monthly meetup here in London, so if you're local and you haven't been to one of the meetups yet, or if you're passing by, by all means sign up on the Meetup page. We are organizing meetups every third Wednesday of the month, in Central London.

Mark Bates: Fantastic. Do you have a Twitter account that perhaps people can follow?

Kat Zień: We do, surprisingly, @londongophers.

Mark Bates: Wow, who would have thought...?!

Mat Ryer: And Kat, I noticed you didn't say your last name. Is that because you don't know how to read it properly, like me...?

Kat Zień: Yeah... [laughs]

Mark Bates: That's another one of those names we give Mat.

Kat Zień: It's Kat Zień.

Mat Ryer: Zień. Easy.

Kat Zień: Gets better every time.

Mark Bates: There you go, yeah. [laughter] In addition to the London Gophers and all their great support, and the support they get from their routine, recurring sponsors, we also wanna thank JFrog. Not for the people at home, they honestly don't know what's going on... But for you in the audience, those nice, tasty beverages you got when you walked in the door - that was courtesy of JFrog. They sponsored the welcome drinks tonight. They have a little booth in the back, where they're giving away lots of free stuff... So a big round for them for footing the bill for tonight. Thank you. [crowd applause]

Mat Ryer: And now legally speaking, that's all the stuff that we have to say, is now said... So now we really are on our own. Normally, when we do the podcast, the idea is we do the live show, and it's kind of relaxed, and we're not too serious about it, and then hopefully they can find good bits to make into a podcast at some point... So that's what we'll do this time. So if it seems bad, it's not. That's just life.

Mark Bates: It's an illusion.

Mat Ryer: Yeah.

Kat Zień: I forgot to mention one thing...

Mark Bates: Go on.

Kat Zień: We have this Gopher plushie here, and this is a prize for the best question for tonight. We're gonna take some questions from the audience at the end, and the best question is gonna win the Gopher plushie.

Mark Bates: And Mat does have a random gift he's been desperate to give away for some bizarre reason.

Mat Ryer: [00:08:07.26] I have a GopherCon towel, from the wrong GopherCon...

Mark Bates: A beach towel. From -- yeah, the wrong GopherCon.

Mat Ryer: Yeah. It's from the other GopherCon, but it's still a towel. If you like being dry...

Liz Rice: Is it unused?

Mat Ryer: It's unused, yeah. I hope... It wouldn't be dry. [laughter]

Mark Bates: It is a soiled beach towel. For all you British gophers out there, you love going to the beach, so the next time you're sitting under an umbrella, in the rain, eating an Ice Lolly in a sweater, you'll have a lovely Gopher towel underneath you.

Mat Ryer: That's why it's soiled, because we sit on soil. [laughter]

Mark Bates: This is what happens when we go off-script.

Mat Ryer: Oh, yeah...

Mark Bates: See? Look, now you're just moaning at us. [laughter]

Mat Ryer: That's fine. Moaning is acceptable, because at least you can hear it on the podcast, [unintelligible 00:08:50.01] in real life. Otherwise I do think people are gonna question that.

Mark Bates: Fair enough. I think we should start.

Mat Ryer: I think we should start, too. Today we decided we're gonna start by talking about the sparkle emoji in the standard library. Again, I am better in text, but it's the sparkle, the gold, or the magic in the standard library.

Mark Bates: I actually pinged Gotham and I said we're gonna be talking about the gems of the standard library, and he goes "Well, this is the wrong conference. We're supposed to be talking about [unintelligible 00:09:18.16] Ruby." [laughter] Yeah, so we really are on point with the name of this, absolutely, because none of us know what it is.

Mat Ryer: Yeah. It's the bits of the standard library that each of us have kind of fallen some more in love with, to varying degrees. I've fallen with mine a lot... In love. But others maybe not so much. [laughter] Exactly. Just a quick example of something that would hopefully get cut out of the podcast, [laughter] so no one even knows about it. But the editors are... I won't say lazy, but they leave it all in, basically.

Mark Bates: Let's start -- I think we should start right here in the middle, with Kat. Kat, can you give us a little nugget of gold? A little something that maybe the audience here may or may not know about in the standard library, that you just love and kind of think "Oh, I wish more people knew about this."

Kat Zień: I hope everyone knows about it. If not, they should definitely look it up. My favorite one is Context. I just find this (surprisingly) the most usable day-to-day package, for me... Because it just solves a problem that I've always had. My background is in PHP, so that's a lot of web applications, a lot of requests and responses... And I always struggled with how much data do you pass along, and where do I pass along this data, and I ended up having function names with 14 parameters in, because we needed to pass in all the data. And then when I started doing Go and I discovered Context, I'm like "This is a solution to that problem. And it's very elegant." And that's only one side of the package.

It's a really weirdly split brain package, because on one side you've got the params that you can pass in in the context, and on the other hand you've got the whole goroutine management side of things - the cancellation, and timeouts, and deadlines... And I find that this is just a great tool to manage your channels, your goroutines, and everything. And it's very elegant, it's very simple, it's an interface with like three methods, or something...

Gautam Rege: Four, yeah.

Kat Zień: Four, yeah. Because the request param is at the forefront. So yeah, I love it. I use it pretty much daily.

Mark Bates: Could you give us an example where you've abused it? You've done something you probably shouldn't have with Context?

Kat Zień: I've been very good at making sure that the -- I think the only rule with the params side of things is just passing params that don't change throughout the lifecycle of the request. So I didn't cheat, I didn't put my database connection in there, or something... [laughter] I've always avoided this. I've been a good citizen.

And then I remember reading a bunch of books which all used Context for examples of deadlines and cancellations and timeouts in a really clever way... So I've tried to do that. I can't say I do this a lot day-to-day, because most of the time when you use libraries it's all taken care of for you... But under the hood it still uses the context. And then when my request times out, I see in the logs "context timeout", so I'm like "Yeah...! Context!" [laughs]

Mat Ryer: [00:12:13.20] For anybody that doesn't know why that got a laugh, when you said you don't put the database connection in there... Maybe we should talk a bit about that. Because when you do use the values inside a context --

Mark Bates: Yeah, which is the context with value, right?

Mat Ryer: Context with value... They're sort of hidden dependencies; they can be.

Kat Zień: Yeah.

Mark Bates: Sideline APIs, they're often referred to as, yeah.

Kat Zień: The main gotcha with this is that at no point in the lifecycle of your thread -- you don't know what's inside the context, and you don't have a list of the values that you can access, so you have to know that they're there. So the gotcha with this is only use values that throughout the whole lifecycle you can expect that value to be there, and also not mission-critical values; so if it's not there, it's not the end of the world.

A very common use case is log parameters. If you wanna log something and you wanna add a bunch of metadata to your log lines, then you can store them in a context. But if they're not there, it's not the end of the world, because they just won't get logged. The app still runs, it's fine. Whereas if you rely on your database connection being there - and by the way, context values are not guarded in any way against being overwritten or changed halfway through; you basically have no guarantees that what you've put in at the beginning is the same at the end.

Mark Bates: Yeah, I always say they should be user request-specific.

Kat Zień: Yeah.

Mark Bates: Things that you'd get necessarily, like if someone made an HTTP request - you'd see a session ID, or user ID... Things that are very specific to that.

Kat Zień: Yeah, small, specific and constant, and not mission-critical.

Gautam Rege: Yeah, I think most microservices are now just coming up with a paradigm where you must have the context pass around everywhere, interface properly, and the context. If that happens, you actually have a lot of control over what's happening... So it definitely helps.

Kat Zień: Yeah.

Mat Ryer: I like the fact that the Done method returns a channel, which gets closed when the context is canceled. So then if you do have concurrent code and you use the Select block, it's very easy for one of the cases to just be the Done of the context, and you can do other things, and it'll keep doing those other things until that context gets canceled, and then you can gracefully shut down. It's actually a really easy way to do graceful shutdowns.

Mark Bates: Yeah, one of my favorite parts is the fact that -- if you're unfamiliar with it, the way you create context is you're actually continually wrapping them; so you're always kind of creating this node of context, which means you can start with, say, the user request. On HTTP request there's a context; so if the user shuts their browser, for example, that context gets canceled. And you can use that as like your primary context let's say in a web app, and then spawn that off to other things, and they can then wrap that with their own timeouts, their own cancellations, their own values, and it all kind of trickles down. Or just this little bit cancels itself. I think that's a really clever pattern they used to do that, the node pattern.

Kat Zień: Yeah. I think the cool thing as well is the Context package itself -- I'm a bit hazy on the implementation details, but I know that it can flatten itself, unpack itself. If you have a bunch of nested context, you call this "context-something-something", that you can just flattened the context to the most recent values.

Mark Bates: Okay, that's new...

Kat Zień: I've seen that -- that's why I said I'm a bit hazy on the details. If you have a bunch of nested context, and you call that function, it'll bring up the compound context, with all the ones that were nested, just flattened.

Mark Bates: Oh, interesting.

Kat Zień: I need to dig up the name.

Mark Bates: Yeah, I'm curious. Send it to me. Or post it on Twitter, so everybody else sees it. Don't just send it to me privately.

Kat Zień: I'll do it now. And show notes later.

Mark Bates: I wanna get smarter than you, so don't send it to them. So if you don't know the internals... If you've never seen it, Francesc Campoy actually did two videos for JustForFunc about context when it first came out. And one of them I think is just truly wonderful, where he basically rebuilds almost the entire package from scratch. It's really clever, and I highly recommend you watch it. It shows use of goroutines and channels, and kind of keeping all this stuff in play, and how this context cancellation itself works. It's an excellent video.

Mat Ryer: [00:16:15.02] Brilliant choice, Kat.

Mark Bates: Yeah.

Mat Ryer: And would you say you just like the Context package, you love it, or you're in love with it?

Kat Zień: I love it, because it makes my life so much easier. I find it just the most useful day-to-day. At work we actually have a thing where our requests struct, an internal request thing - it sort of inherits the context interface, so you can pass interchangeably the context [unintelligible 00:16:37.29] and that just makes life so much easier. I just love it, because our logging library requires the context for all the extra params, but I can just pass in the request and I don't need to do any marshaling in between, or anything.

Mat Ryer: Oh, so they've implemented the Context interface itself.

Kat Zień: Yeah.

Mat Ryer: So then you can provide your own context objects like that, can't you?

Kat Zień: Yeah.

Mat Ryer: And Buffalo does this too, doesn't it?

Mark Bates: Yeah, Buffalo does do that. We do it in a lot of projects as well, and it's a pattern I recommend people actually use. A lot of times you just kind of embed a context.context, which is obviously not very good for the whole "Don't stutter in Go" thing... [laughs] As everything is just context.context everywhere; but you can take in the context that someone gives you and then build your own, and do different things with it. Maybe provide your own value implementation, which is what Buffalo does; it has a map of your request parameters, and stuff like that.

Kat Zień: Yeah. You can also do it the other way around - if your struct implements the context interface, your code can deal with either the native context or the struct, and then check, like "Oh, if this struct..." For us, for example, our requests have a context, but then our logging library checks if the thing passed in is actually an instance of that request, not just the pure context; then you know that the request struct also has a bunch of more details that you can fish in and put in the logging library... So you can do it the other way around as well. But yeah, it's seamless and it's so great. I use it every day. Every time you implement a handler, you encounter the context, so...

Gautam Rege: Interestingly, also, we're always talking about the context of a web request. I have seen a couple of cases where people have misused, or wrongly used the context, just because it's cool.

Mark Bates: Give us an example.

Mat Ryer: In a command, or something, you mean?

Gautam Rege: Yeah...

Mat Ryer: I'm all of those people. [laughter]

Gautam Rege: ...and then you end up doing context.TODO(). [laughter] Just put up a dummy context instead.

Mat Ryer: I use it in a command. I'll have the main function will trap the signal, and I'll cancel a context, which I then pass into just some other run function. Dave Cheney told me off on Twitter for doing this.

Gautam Rege: That's Dave.

Mat Ryer: That's Dave, yeah. Because he said it's for requests only. But in a command, in a way, I think that IS the request.

Mark Bates: Yeah. It's a user running the CLI, and...

Liz Rice: You mean somebody at a CLI typing in a command?

Mat Ryer: Yeah.

Liz Rice: That's a request...

Mat Ryer: Yeah.

Liz Rice: ...and asking you to do something.

Mark Bates: I often pass context in as the first value to a new, for example.

Mat Ryer: Where were you when Dave was having a go at me on Twitter? [laughter] Too little, too late. No, but here's the thing...

Mark Bates: Who trusts what Dave Cheney says, really...? [laughter]

Mat Ryer: That's an example of something that might actually get cut out. [laughter]

Mark Bates: Everybody right now is tweeting at Dave. "Mark just said "Who is Dave, really?" [laughter]

Mat Ryer: But the thing about the command, and using requests and context in that sense is if you're doing some long process, if you trap the signal, then Cmd+C will cancel that context and you can just unwind everything. It's a properly nice way to do that graceful shutdown. It fits perfectly.

Mark Bates: I agree.

Liz Rice: I think that's nice.

Gautam Rege: [00:19:47.08] You need to be able to use it. I've seen cases where we were using MongoDB, and there's a lot of context being used, and I've seen code where people were like "Dude, I don't know why it's there, so I just put a dummy context and make it happen", and that comes and bites you later on, because suddenly your context is changed from a request. So when people are building bottom-up; you build the code first, and then you have an API added to it, and that context is misused, you [unintelligible 00:20:10.26] And the HTTP request which finally comes through is not using the context there, and it's failing, and you do not realize it until all your test cases bypass it. You realize it in production. So you have to be a little careful--

Mat Ryer: I never got that TODO... I actually don't get that.

Mark Bates: Well, context.TODO() differs from context.Background() in that they're the exact same thing, but the idea is you can grep for TODO in your code.

Mat Ryer: Well, let's just always do that. Let's just write Javascript.

Gautam Rege: If you don't know what to do, just TODO.

Mat Ryer: Yeah. If you just can take anything, TODO. Anyway, cancel.

Mark Bates: I have actually a question for the panel.

Mat Ryer: I've just canceled the context.

Mark Bates: Yeah, you did. Good job. We're almost at our timeline, by the way... We're almost exceeding that. I have a question for the panel - when they introduced contexts into the standard library in 1.7, obviously they tried to retrofit it wherever they could... And because of that we now have this exec, exec with context, or exec.Command, exec.CommandContext, right? We now have two versions of every API, or a lot of APIs. The SQL package has a very similar thing. What do people feel like...? Do you feel like you should also offer two implementations, one that has a context and one that doesn't? Do you think we should only just take the context?

Mat Ryer: The only reason there's two is because context came after, and they have the version 1--

Mark Bates: That's almost what I've just said when I said they retrofitted in 1.7... [laughter] Almost the same thing. I mean, not quite... You say it a lot nicer with the accent.

Mat Ryer: Exactly. I'm giving people a treat.

Mark Bates: You really are.

Mat Ryer: It's not a treat here, we're in London. Everyone talks like me. They know I'm shit... That's gonna get cut out, I think. [laughter]

Mark Bates: But let me ask the question to the panel...

Liz Rice: It's the compatibility promise, isn't it? You can't introduce something like that and just... Context is useful, I think we've just established that, so... What other options do you have?

Mark Bates: Okay, so let me rephrase the question. In Go 2 - the infamous Go 2 - comes out alongside TextMate 2, Perl 6, and all the other ones... [laughter] So when Go 2 finally comes out and we're all out of the game, because we've retired for 20 years, should they remove the non-context versions?

Kat Zień: I wouldn't necessarily say remove -- I mean, in 2 yes, because you're not bound with the backwards compatibility promise... And I feel like because context provides an easy way to just put in a dummy context if you don't need it, even if every function requires it, there's just an easy way for you to not use it if you don't want to. I feel like if there was no context.Background() or context.TODO(), it would be kind of unfair to always force people to have the context. But because you have an easy way out, I don't see a problem with just forcing it for every function. It's kind of become a standard anyway, where the first param is always context anyway, so...

Mark Bates: Right. Which has led to so many fun proposals on Golang issues, right? ...of "Do we have some sort of current context, that we can just grab, and we don't have to keep passing it around?" I don't think we have time for that discussion.

Mat Ryer: I wouldn't mind a copy context. IO copy with a context...

Mark Bates: Oh yeah, that would be cool.

Mat Ryer: Someone did write one; there is one that you can use.

Mark Bates: Oh, interesting. Okay, I think...

Mat Ryer: We should move on, because--

Mark Bates: Yeah, I'd love to hear some other ones. Gautam, tell us a little bit about your favorite parts of the standard library.

Gautam Rege: When I started writing -- you know what is the interesting part? I realized that everything is about the name... So my favorite package, luckily or unluckily, is the regexp. Not because it's my third name - my third name is Rege, and it's there in the package name. I actually genuinely like regular expressions, and I think it is one of the most important things to learn; not particularly in Go, but in general.

I always say that if you know regular expressions, your Linux commands and Vim, you're a programmer. [laughter] All the Emacs haters out there - too bad.

Mat Ryer: [00:24:18.03] Other IDEs are available. We should just say that.

Mark Bates: Yeah, we don't discriminate against the IDEs... Except for TextMate 2, which hasn't come out yet, so you're good. [laughter]

Gautam Rege: Recently I looked at regexp/syntax package, and that's pretty neat, because it's got a lot of information about the latest nuances of using regular expressions, including your named captures and your greedy searches, in the right context, with the Perl-based as well as the ASCII-based syntaxes. And I think it's a must-read for everyone, if not to use it, and stop using Stack Overflow or Google to find out what is the fastest way to find a regular expression, copy-paste it and put it in... Because it causes problems later on.

Mat Ryer: Especially if you copy and paste from the top... Because that's the question. [laughter] I make that mistake all the time. "Well, I just got this from Stack Overflow. From the question. None of it works!"

Gautam Rege: That's taking laziness to the next level.

Mat Ryer: Thank you. Thank you.

Mark Bates: This package is amazing, because it really does show everything. There's more to it, obviously, and there's a lot of stuff -- there's actual code that happens on the syntax package too, but the documentation at the top is fantastic, and worth it alone, and I often refer to it... Like daily.

Gautam Rege: A lot of times we don't end up using the captures. It's been there since the regular expressions [unintelligible 00:25:40.14] but we tend to miss out and write a lot more code; you just use substring, and parse, and figure out where the captures would actually just give you the [unintelligible 00:25:49.20]

Mark Bates: Can you give us an example where that's really helped you in your code? Apart from just simple regular expressions...

Gautam Rege: Let me think about it...

Mark Bates: Yeah, we've got time. We'll wait.

Liz Rice: [unintelligible 00:26:03.16] Take your time, it's fine.

Gautam Rege: Yeah... So there was a case where we were trying to map out the entire URI, with the username, password, [unintelligible 00:26:14.06] everything together...

Mark Bates: So you wanted to write your own URI.parse.

Gautam Rege: Yeah. And it turned out to be a nightmare, because somebody just tried to go the distance, saying "Oh, the host could actually have a a.b.c.d," and they started using a substring, and iterating all that. And then I saw the code - the code had already become like 100 lines of code, and I'm like "Dude, have you not heard of captures? Just capture it and then just match it." It's just easy sometimes to look at the documentation first and implement it.

Mark Bates: When you say captures, for those who maybe don't know the regex package - because that's why we're here for - what do you mean by captures? Just the parentheses?

Gautam Rege: Yeah. You were trying to match a group of parentheses, with or without greedy searches. So you want to actually find out if -- say, for example, if you want to match just a subdomain; but a subdomain could actually go really -- if you look at the canonical name for an AWS host, it's huge. But it has everything in it, and you want to find out just the hosting, not the rest of it... You can always capture it, without greedy searches, or you can find out if it's matching the right pattern, using captures, the parentheses, in your regular expression, just to check.

Well, there are ways that you can even replace stuff in it... But not recommended for readability purposes. But if you're just getting through the regexp syntax package, there's a lot of clarity which comes out. You can even name a captured feed. [unintelligible 00:27:40.17] so you can actually process it better.

Mark Bates: That's cool.

Mat Ryer: That is cool. My problem with regex is it's too easy.

Mark Bates: Yeah, that's everybody's problem.

Mat Ryer: I like a challenge. [laughter] It's like "What? Okay..."

Mark Bates: Stack Overflow...! Oh, that's clearly human-readable. Let's make it a bit more difficult.

Mat Ryer: But yeah, once you learn it - of course.

Gautam Rege: It's fun, because then you're not just coding to finish a job, but you're actually doing it well.

Mat Ryer: Yeah. You're casting spells as well, at the same time.

Mark Bates: And I'm not gonna lie, it feels amazing when you get a regex that works. Like, truly amazing... Doesn't it? You're like "I won the internet today. I got the regex to compile and do what I wanted it to do."

Liz Rice: [00:28:26.25] I love those Regex101, where you can go and live-test your regex.

Kat Zień: I was gonna say...

Liz Rice: It's brilliant. [unintelligible 00:28:28.17]

Mark Bates: There's actually, which does Go regular expressions. Whoever wrote it though was an amazing developer, and they wrote it in Buffalo... And they're just really handsome. [laughter] That would be me. Just to clarify... Not Mat. Because Mat's like "I don't remember writing that..." [laughter] I did. But yeah, it's Rubular for Go.

Kat Zień: So how did you check your side? Because I always wonder... It's like the chicken and egg with those online regex checkers, for like "Well, if we check our regex with them, who do they check with?"

Mark Bates: We compile it and we use the regex package, and give you the result... [laughs]

Kat Zień: But if you think about it, if there's a bug on that website, then everybody else's regex is wrong, and they obviously can't find their own bugs...

Mark Bates: No, because you just give me a string of regex, I run it through compile, and it either compiles or not.

Kat Zień: True, yeah.

Mark Bates: It's not like I'm sitting there, parsing -- I don't have a big regex that parses regex. If you think that's what I'm doing on my weekends... [laughter]

Liz Rice: [unintelligible 00:29:40.11]

Mark Bates: Yes, exactly.

Kat Zień: So they're still like a chicken and egg, because if you just run it through compile, then what checks to compile...?

Mark Bates: Well, the Go team... [laughter]

Kat Zień: Anyway, anyway... Dead end.

Mark Bates: I didn't need this [unintelligible 00:29:55.16]

Mat Ryer: No, but that's a good point, that Kat brings up - who watches the regex watch people? We may never know.

Kat Zień: I've run into a few cases with regex where something works in one language and doesn't work in the other language, and that always puzzles me.

Mat Ryer: Yeah. It's like your last name.

Kat Zień: That just doesn't compile anywhere.

Mat Ryer: It just doesn't compile in my brain. Not when I see it written down.

Mark Bates: I believe Go does implement Perl-style regex, correct?

Kat Zień: I think so, yeah. Not the PHP one, because that never worked.

Mark Bates: Yeah. It doesn't match Ruby's either. There are a few places where Ruby doesn't match.

Gautam Rege: Interesting... Which is why I think everyone should actually look at that package documentation, because you know there is one way to do it, and that's the only way you wanna look at it.

Mat Ryer: I can't argue with that.

Mark Bates: Yeah. And often, if you read the documentation, you'll see cool things; at the top, you can do :alpha: and that's all of the alpha characters. You don't have to specify them. You can do :digits: and all these nice combinations, very readable words, as opposed to /d or /D or whatever.

Liz Rice: Question for you - can an alpha cover all the accented characters, and non-roman characters?

Gautam Rege: Alpha is only for ASCII.

Liz Rice: Just ASCII, okay.

Gautam Rege: That's the problem with wide characters. If you're doing wide characters, regular expressions is not a beast.

Mark Bates: What about UTF8? Go has UTF8 support built in. If you range over Hello World Chinese characters, you're gonna get the nice spaces, and the index is gonna jump appropriately, and you're gonna get a full character... Unlike other languages, where you get a third of a character. How does that actually work with regex? Are you able to regex over UTF8 characters?

Gautam Rege: I think UTF8 support is there for regular expressions support already. And I don't think it gets to UTF8, because then [unintelligible 00:31:43.20] you're looking at maybe some Japanese or a Chinese character (a kanji), you cannot compare it to UTF8. You'll have to have the regular expression support wide characters for it. I haven't tried it, because I've not gone down to typing out one of the kanji stuff in the regular expression... It'd be fun, but... It should support it.

Mark Bates: [00:32:09.22] There you go. Fantastic. I love it.

Mat Ryer: Great, yeah.

Liz Rice: My very first professional job was doing double-byte character support in a 3270 emulator, if I remember right. It was horrible.

Mark Bates: Now she can write that 3270 emulator in 20 minutes on stage, and for fun. [laughter] She cracks her knuckles, and goes "Hang on..."

Liz Rice: I'll just get my computer our...

Mark Bates: Yeah, exactly. She'll do it for us by the end of the podcast. [laughter]

Mat Ryer: But Liz, you were mentioning earlier about the io.Reader and io.Writer...

Liz Rice: Yeah, so when we were first discussing doing this podcast on this topic of the Go standard library, one of the things that strikes me if you think about the whole of it is how prevalent really nice interfaces like io.Reader and io.Writer are, which means you can easily plug and play with different things that you want to input or output... And also, the richness of the things that you can plug into that interface. You wanna write out some JSON? That's there for you. You wanna write out to a file? That's there for you. You wanna write out to --

Mark Bates: They're brilliant, simple interfaces, aren't they? They're just so simple and brilliant.

Liz Rice: They're so simple, and they're so pluggable and so testable... Which is great.

Gautam Rege: My favorite part of the io.Reader and io.Writer is the design they've used for the interfacing. It's beautiful. It's just something that you should actually look at, get into the details of the design, and try to implement something like that in your work. It really helps. So beautiful and smooth.

Liz Rice: And a number of times where we have -- somebody says "It'd be really nice if you could output this report in a different format", and we go "Well, okay. Fine." We'll do that, it's easy.

Mark Bates: I'm gonna gzip it - boom. It's still just a writer. The bytes buffer - just a writer file. What I love about them is the symmetry of the read/write interface. They're identical.

Mat Ryer: True.

Mark Bates: It's just read and write, and it's just a beautiful symmetry between the two. They're identical-looking interfaces, and it's very beautiful, very clean, isn't it?

Liz Rice: And I think you'd be hard pushed to find another language that has that kind of breadth of similarity between the interfaces you get from different packages. It's a beautiful thing.

Mat Ryer: The real magic as well I think is the fact that they're single-method interfaces.

Mark Bates: Yeah.

Mat Ryer: An interface with one method is so easy to implement. It gets implemented a lot, and this one - that's a good exmaple of it. It's very exciting when you're doing your own projects, when you -- I feel like it's a discovery. You discover a single-method interface, and then you can do things like the trick of using other types as the base, and then implementing that interface. Like the HandleFunc does it for handles.

Mark Bates: Yeah, I actually show that in my workshop today. That's one of my favorites. Just the way Go type systems work, where you can say "Type handler func is a func that takes a response writer and a pointer to request", and then on that you can implement another method that calls itself and implements the HTTP handler interface.

Mat Ryer: Yes. So then when you need to use that type, you don't need to build a struct and implement that type; you can just use a function...

Mark Bates: Yeah.

Mat Ryer: it gets used even more. But I agree, reader and writer... And they are quite strange, I think. When you first come to Go, seeing a read method that takes in a slice of bytes and just returns an int or an error is a strange thing... But it really reflects what's really happening under the hood.

Gautam Rege: Absolutely.

Mat Ryer: So it has that mechanical [unintelligible 00:35:40.17]

Mark Bates: I think for me it was more just like "This can't possibly be it." When I first came to it, I'm like "It's just one method. How is that writing? Isn't there other stuff I need to do when I'm writing stuff or reading stuff?" And yeah, there is, and there are other interfaces. Maybe you wanna close it, and there's a closer interface. Those are just amazing interfaces. I can see why you like them.

Liz Rice: I do.

Mark Bates: Yeah, we should all.

Liz Rice: [00:36:09.05] And there's so much about this standard library that gives you just so much power out of the box. The other thing that kind of struck me when we first talked about doing this podcast was "Well, net/http - everything you need to write a website, right there, in a few lines of code."

Mark Bates: Buffalo users, don't listen to her. [laughter] She doesn't know what she's talking about. You need Buffalo.

Liz Rice: The fact that you can get a web server running - like you made the point, Kat - in one line of code... It's amazing. And again, point to another language where that's possible out of the standard library. It's really nice.

Mark Bates: What I love about that - most standard libraries have web packages. Ruby, for example, has a built-in web server called WEBrick, which kind of gives you an idea of how good a server it is - it's called WEBrick... [laughter] Yeah, it's beautiful. But you wouldn't use it out of the standard library; you'd use Rails, because it's not useful, it's not designed well, and those packages in the Ruby standard library just aren't able to do what people need it to do, and that's how things like Rails came up. With Go - admittedly, obviously as a maintainer of Buffalo I've got different end goals, which are more user development, and stuff like that... But to just sit there and say "ListenAndServe, here's a function", and "serve this function." It's amazing.

Liz Rice: Yeah. I think the first time I saw it - however many years ago when I first saw that - I'm just looking at it thinking "How can that possibly be it?" A bit like what you were saying about io.Reader...

Mark Bates: "How does that work...?"

Liz Rice: "Surely there must be more to it..." And then you realize, "Well, actually no." There's a ton of defaults that it can take care of, and if you wanna mess with those defaults, you can. But you don't have to. And ta-da! A website in one line of code. It's nice.

Mark Bates: And what I love too is you can actually turn that then into an SSL site with two lines of code. You could take the same muxer that you've just used, the same handler, and just do "Go ListenAndServe on another port." And now you've got port 80 and you've got port 443 running simultaneously, because you've just launched the same muxer in a different goroutine, on a different port. In two lines of code. It's really, really cool. You don't have to really stretch to get there, do you.

Kat Zień: Yeah. And I like that it's pretty safe to use for beginners as well, because things like request timeouts, or connection timeouts - it's not something that you care about when you first start programming... Whereas this one - you just do one line of code and you're excited because you've got a web server running; and then if you wanna dig in, you kind of have... One of my favorite things about Go is that if you go into the source code, they have really nice comments that then become the GoDoc source... And it just really explains what everything is - the connection timeouts, and request timeouts - and you can dig in a bit more, and learn a bit more about how HTTP works under the hood, but you don't have to care if you're a beginner. So it's like a very low barrier to entry.

I remember this struck me a lot when -- so there's a book called The Philosophy of Software Design, by John Ousterhout (I've probably butchered the name). He talks about deep modules and shallow modules, and he gives that exact example. In Go you've got -- say with the io.Reader and io.Writer, you've got an interface with one method, and it's kind of a deep module, because as a user it's just a black box that you call; you don't care what it does under the hood. You don't need to know in order to use it. And if you want to, you can dig in a bit more.

He compares it to Java, where in order to read a file, you need a reader and then you need a buffered reader, and you need a string buffered reader, and you have to know how this works in order to use it. That's the difference. That's why I like Go, because -- HTTP is an example; you can just call that out of the box and treat it like a black box, or you can dig in, but you don't need to. I feel like that's the genius of the design of those packages.

Mark Bates: I think the standard library really does a very -- I've had lots of conversations with the Go team, and I remember I was having one with Steve Francia, who's one of the program managers for the Go team... And we were talking about just this, and he said "The standard library is designed to be building blocks. You can start there, and then layer on top of that more abstractions if you need them."

[00:40:16.09] If you've ever used a SQL package - it's very raw, and it feels quite clunky and cumbersome; and the reason is because that's the building blocks for building more abstractions on top, if you want to. And the same thing with the HTTP package. There are times where I'm like "Ugh, it doesn't do error handling. I wish it returned an error." But that's fine, you can then build an abstraction; I actually just did this little error check thing that takes a handler and it returns a handler, or it returns my own type of [unintelligible 00:40:43.11] and I can do the error handling now in one place. But it's a little abstraction I just build on top of, and the standard library lets you do that, because it's so easy to work with in that way. That's how everybody has their own HTTP router now. [laughter]

Kat Zień: Yeah. I think that's kind of a nice segue to the other package that I think Gautam mentioned, which was the httputil single reverse proxy... Which is another thing on top of HTTP that is very elegant.

Mat Ryer: Tell us about that.. What's the single reverse proxy?

Gautam Rege: This was something that came along, it was not something I was searching for. But it you ever get a chance, have a look at the httputil single host reverse proxy method. Basically, if you want to modify the response that is going out on your HTTP server, you can intercept any kind of these responses and make whatever changes you want. Because you have a reverse proxy there, you can basically tag it along with a particular URL.

Think about this - how easy or difficult is it for you to intercept a redirect request from a server? By default, we just think it's a browser thing, but it's the server who's sending back a 302. Can I intercept that 302 request, and maybe make a change in the the JWT token, or maybe a change in the URL that is getting sent back? We can do that. If you use a single-host reverse proxy method in that, it helps you modify the response; there's a method called "modify response", where you can actually take back the status quo, modify the response and send it back, seamlessly. You'll probably do it when you're in Aqua Security; I'm pretty sure you'll probably do that... Because if you have to preempt somebody from accessing something, this is the easiest way to just deny. So instead of returning a 302, you change the status quo and return a 402.

Mark Bates: One of my favorites is actually the exact opposite of that, which is the RoundTripper interface in the HTTP standard library. Do you know it? You look at me like "What is that...?"

Liz Rice: Yeah, I've used it, and I can't remember what for...

Mark Bates: Yeah, it's one of my favorites. Now, if you read the documentation, it goes on a client; an HTTP client has a default RoundTripper, which is [unintelligible 00:42:56.21]. The documentation will say "If you want to change how the transport mechanism works" - maybe you wanna use a file as a transport system; Unix socket files, for example... You can write your own implementation that does that. Maybe you wanna use a database as the transport mechanism, or whatever it is - you can do that. You can plug this in, and it takes a request and spits out a response, an error on the other side. So you can control that flow. But the documentation says you're not supposed to modify the request, you're never supposed to use it for this; I actually love it for that.

One of the things I like to do -- I do it with a couple things. I will create my own RoundTrippers to do, say "Add a JWT token to all my outgoing requests." So I provide one client that everybody uses, and inside of that it'll automatically tag with JWT, or stuff like that.

I also use it in tests. It's a really fun way of capturing and replaying back third-party APIs. In your tests, you're doing an http.get, you can change the transport mechanism so instead of going to Twitter, or Facebook, whatever you're trying to hit, you can just return back your own stuff. So it's incredibly useful for testing and mocking out the other side of the http.get. It's easy to mock out your own server, but sometimes it's just easier to capture a payload from Twitter, store it on the disk and just replay it using a transport.

Kat Zień: [00:44:24.20] That's really cool.

Mark Bates: So it's like the other side of the reverse proxy part; it's the outgoing part. That's one of my favorite little bits.

Kat Zień: Yeah. We used reverse proxies for a very specific use case at the previous company... We had a legacy application, and we kind of wanted to use the Strangler pattern; you sort of slowly carve out -- you strangle your old legacy app by slowly carving out bits of it and putting it on the new stack, until eventually the old thing can just die, because nothing's using it anymore. And so we had this problem of -- we had a website and we wanted some of the parts of the website to be served by new services, and most of it to still go to the legacy servers... So we had to put something in between. We used essentially reverse proxy.

I remember my manager coming to me and saying "Can you write a reverse proxy in Go that will help us do this?" I was like "Oh, my God..." And then I discovered it's one line.

Gautam Rege: One line of code.

Kat Zień: It's called a Single Reverse Proxy, job done.

Mat Ryer: "Yeah, I'll give it my best shot. It might take me a couple of weeks..." [laughter]

Mark Bates: Yeah... One line.

Kat Zień: That's what I did... That was my holidays.

Mark Bates: I'm gonna go work at it at home. I'll see you in a few weeks. I'll come back with a tan. [laughter]

Kat Zień: Yeah. I was genuinely scared. I was like "Oh my God, I don't know", and then it's one line. So it's really nice, and it gives you a way to basically receive a request, and then decide "Okay, if this request comes with this domain", or based on whatever params you want, you just direct it to one service; otherwise you direct it to the legacy app. That was really nice, and it was really easy. It was really nice to have that routing logic in a separate Go app.

Mat Ryer: Yeah, and you get to use Go code to make these decisions.

Mark Bates: Yeah, really. One of the things I played with and I never actually got a chance to finish it -- with Buffalo, for example, we watch your go files, and as your go files change, we rebuild it; and if there's an error, we display that error back to you from the build, but we do that with kind of like just faking it out a little bit, using a file and serving it, and it's not particularly good. And one of the things I played with was a reverse proxy, where when you actually go to port 3000, it goes to this dev dashboard thing, and proxies it through to your application, which is now running on a different port. And if that crashes, we can just proxy that error back to you. But I just need more free time... But it's a wonderful, wonderful tool if you've never used it.

Break: [00:46:37.07]

Mark Bates: Speaking of time, Mat... It's 7:50.

Mat Ryer: I thought you were gonna talk about the Time package. [laughter]

Mark Bates: Why? Time is on my side, mate. I don't need to worry about it. No? Okay, fine. We can cut that out later.

Mat Ryer: Yeah, don't worry too much about the time. At some point things will end, and then we will be fine.

Mark Bates: I'd love to give these lovely people a shot at asking some of our fine panelists some questions, and maybe win that gopher and that used beach towel of yours.

Mat Ryer: Great ideal. Soiled.

Mark Bates: Hang on a second... Paul Jolly, where are you, sir? He was our mic gopher. He's at the dinner... He left. [laughter] He was like "I'll volunteer to walk around with a mic", and he went to dinner. Thank you, Paul.

Mat Ryer: Did the take the mic to dinner?

Mark Bates: He did! That chewing you hear in the background is Paul.

Mat Ryer: Let's just turn it on and see what he's having. "Hello, we're going live over to Paul..." [laughter]

Liz Rice: I've seen they're livestreaming it... Can't they just send us some questions from the dinner--

Mark Bates: Okay, so Dom's gonna walk around... We've got a question right over here down front, the very first hand, over here. See my finger? I'm pointing -- over here. Dom? Oh, okay, sorry. [laughter] I'm looking this way - you, with that lovely yellow shirt... How am I supposed to see [unintelligible 00:49:54.24]

Audience Member: Have you ever used the len operator on a buffered channel, and why?

Mark Bates: The len?

Audience Member: Yes.

Mark Bates: That came up today, I think in Cory's... No, because I don't use buffered channels.

Mat Ryer: That's for buffered channels, right?

Mark Bates: Yes.

Mat Ryer: Okay. Because you can also set the capacity.

Mark Bates: Or you can read the capacity and you can read the len. If you have a buffered channel of 10, the capacity would be 10, and the len would be 4 maybe.

Gautam Rege: Yeah, but you wanna be careful using it, because you'll probably get an inconsistent result.

Mark Bates: Yeah, it's not safe. And you shouldn't be using buffered channels, so... [laughter] It's not a problem.

Mat Ryer: One use case for buffered channels that I find to be great is when you wanna control how many active goroutines are running. If you wanted to limit them, what you can do is create a buffered channel, and then at the start, when your goroutine is gonna do some work - or before that - it puts something in the channel. Say you've got five slots in this channel; the first five of those will be fine, and they'll unblock, because there'll be space in this buffer. The sixth one is gonna block, because this channel is full, and then it's gonna wait until -- and then what you do at the end when you finished processing, you read from the channel to release that thing in the semaphore, and then that leaves a space for the next one to go in. That's a way you can throttle - without much otherwise complexity in the code - how many concurrent things are gonna run, and the code stays relatively easy to read.

Liz Rice: [unintelligible 00:51:31.16] just the other week, and that was exactly what I suggested.

Mark Bates: I do it the opposite way, where let's say I have a channel of stuff, I launch maybe five goroutines - that's my limit - and they're just ranging over the channel, so whichever one picks it up first, does it; then I don't have to use buffered channels.

Gautam Rege: I also strongly believe that you should know the number of goroutines that are gonna spawned, and if it's going to be dynamically increasing, it can actually create more problems everywhere. I wouldn't still recommend using len on a buffered channel at anytime, because it's risky, but the pooling of goroutines, or throttling them, or limiting them over this - I think we could debate on that one.

Mat Ryer: [00:52:16.05] Okay, yeah. Well, I know it works... I don't just kick off loads of goroutines. The kicking off of a goroutine is what's blocked by that channel, so I do know how many goroutines are running at one time.

Gautam Rege: Yeah, that's good.

Mat Ryer: It's about readability. It's easier to read. But no, we'll go in the car park after and take shirts off and have a full fight. [laughter] No probs.

Mark Bates: There's a knife fight going to happen over this... Okay, fantastic. Brilliant.

Gautam Rege: The person with lesser hair wins. [laughter]

Mark Bates: Okay, Dom's got a question over there then...

Audience Member: Can I ask a non-technical question, is that okay?

Mat Ryer: Yeah.

Audience Member: Okay. My question would be - because I'm kind of new to tech - if your life was like a storybook, and each chapter is a year, what would be a name of an influential chapter? For example, an example for me would be like "Chapter 22 - It's Go Time", because that's when I started learning Go.

Mat Ryer: And 22 is your age, and that's the chapter...

Audience Member: [unintelligible 00:53:21.27]

Mat Ryer: And every chapter is a year?

Audience Member: Yes.

Mat Ryer: That's a long chapter.

Liz Rice: Every chapter in my book is 21. I'm just... [laughter]

Mark Bates: So you're asking us what we'd call the current year of our lives?

Audience Member: Well, you could go with the current year of your life, but more of like an influential year. Or anything really - the current year, a year that might be influential to you in terms of your growth as a technical person...

Mark Bates: Some of us have been at this for 20.

Liz Rice: It's gonna take a while.

Mark Bates: It's gonna take a while... [laughter]

Audience Member: Well, just pick one year... Like, chapter 22 - that's when you were 22.

Kat Zień: Pick one year...

Mark Bates: For me it would probably be the very first year I professionally started programming... Which would unfortunately be 20 years ago. I'm dating myself, but 20 years this year.

Mat Ryer: You're dating yourself... [laughter] Is that like a new app? It's for people who can't find love...

Mark Bates: Well, personally I think I'm quite fanciable... So yeah, you know, I take myself out to the movies, and dinner... I treat myself right.

Mat Ryer: Yeah, but why is it not going very well? That's the thing.

Mark Bates: It's really not. I've broken up with myself several times... Especially the past few years. [laughter] But for me it was actually my very first year of programming, because -- if you don't know my background, I actually have a degree in music, so obviously not computer science. So when I got my first job, it was the dotcom boom of the '90s, and if you could spell HTML, you got a job. And if you knew what it meant, it was like another 5k a year. It was wonderful.

Gautam Rege: [unintelligible 00:54:41.04]

Mark Bates: Yeah, exactly. 1999... And I happened to find this job in Boston where the developers on the team were just spectacular, and they were more than happy to sit with me and teach me, and show me how to write code, and how to write good code, and how to read code, and how to understand code. So to me, the lessons I learned that very first year of programming have stuck with me to this day, and it's one of the reasons I quite enjoy mentoring, because it was such a big part of my learning process.

In 1999 we didn't have a ton of books on programming, we certainly didn't have tons of online resources and videos and conferences, and all this sort of stuff online... So you could only learn from other people. That to me was the most valuable thing that year - learning from these professionals, and these people who knew what they were doing, and taught me some wonderful things.

Mat Ryer: That's lovely. Do you stay in touch with them?

Mark Bates: I absolutely do, yeah. I have some very good friends, and we still see each other. I was just at one of my friends' house about a month ago, having dinner. Yeah, so I still see these people 20 years later; they were at my wedding, I was at their wedding... Just lovely people, and we still stay in touch.

Mat Ryer: Thanks to Ben for that really complicated question. Does anyone wanna ask a more complicated question? Because that was too easy, to think of your life as a novel.

Mark Bates: Yeah... I didn't give it a name though... I don't know if I have a name for it.

Mat Ryer: Don't worry, we'll do the names later.

Gautam Rege: [00:56:10.14] The Marksman. Um... Sorry.

Mark Bates: That's one of those things we can cut out for Gautam now.

Mat Ryer: We get one cut each. [laughter] You're allowed to embarrass yourself once.

Mark Bates: Mat, you've used like ten.

Audience Member: Okay, so are you ready for a question?

Mat Ryer: Yes.

Audience Member: I'm not really sure, because one of you is really biased in it, but when is the point where you start using a web framework?

Mark Bates: I'll stay away from the question. [laughter] I do have what I think is a valid answer, but I'm gonna stay away from it.

Mat Ryer: Mark's basically like the Clippy version for Buffalo. He's like "Oh, it looks like you're trying to write a web app." He pops up on the screen somehow in the corner. [laughter]

Mark Bates: My opinion, real quick -- but I'd love to hear others' take, obviously... Because yeah, I am slightly biased. But I'm biased in that - coming from something like Rails, what I loved about Rails was the productivity gains. Go - I can very quickly write a very small app, but when I start writing a large app, the structure, the complexity that comes along with large apps, and templating, and sessions, and cookies, and databases, and all that sort of stuff... You know, there's just so much boilerplate you have to write, and that's where I turn to -- I used to turn to Rails, and now I turn to Buffalo, because it's the Go version; I can just get up and running and I can start writing my business logic. That's when I turn to it.

I don't always use Buffalo though. That is actually true - I don't always use it, because it's not always the right solution for what I'm looking for. But I'm curious to see --

Gautam Rege: Yeah, I like the question, because you need to use the right tools for the right job. If you actually wanna build a web application, you might want to rethink about using Go in general.

Mark Bates: No... That's the wrong answer.

Gautam Rege: Hang on, hang on... So if there's just some standard API building work you wanna do, just use Rails. But I'll give you an example - and Mark, you'll actually like this... We needed to put out a very lightweight web server on a Raspberry Pi, and I didn't want to install anything on it. That was the time I actually used Buffalo, and I bundled up the entire thing in one binary and just put it on a Pi.

So there are use cases where you want to use Buffalo exactly, because there's just no dependency for installation. But if you want to build a larger web application, just use the right tools. I've found using Rails for the front interfacing for API, API versioning (whichever way you wanna look at it) and scaling it up, but do all the heavy-lifting maybe using Go. So use multiple languages, be polyglot, be available so that the right tool is being used for the job.

Personally, if you're writing a web application in Go starting from scratch, as long as it's a simple, small application, you're okay. But as the complexity increases with the databases coming in, and your rate limiting, and versioning, and middleware, it just starts getting a lot of lines of code, and people have already done it. So if people have already been there, done that, don't go reinventing the wheel just because you want to use Go.

Mark Bates: Or use the solutions that are already built in Go.

Kat Zień: Yeah, I don't agree with -- I think if you're new to programming, I think that looking at a massive framework can scare you off. You kind of look at it and go like "I don't know what anything is." So I think with a framework you're gonna have to know already what a framework, what MVC, what all of that is. If you're just trying to learn programming, I think it's better to start with just a native little app, with no bells and whistles, no frameworks, so that you can really understand the concepts under the hood. Then, if you've already done it once in another language or something, then yeah, by all means, don't reinvent the wheel.

Another way to go, for me, is something that we do at Monzo - we don't use frameworks, because we have microservices... But we use a combination of libraries and code generation. So we basically bundled all the common logic in libraries, that every little microservice inherits, and they're all code-generated. So if you want a new service, you just code-generate a service template; they're all homogeneous, they all inherit the same libraries for authentication and logging and requests and all of that... So that's another way to go if you don't wanna use an MVC-style framework.

Mat Ryer: [01:00:23.09] How do you describe the services at Monzo?

Kat Zień: Microservices.

Mat Ryer: What do you mean? How do you describe them, how do you define them?

Mark Bates: Blue, little...

Kat Zień: They are single-responsibility --

Mat Ryer: Sorry... When you say "Something gets generated", what does it get generated, and where does it get generated from?

Kat Zień: It gets generated from templates. We have an internal tool called ServiceGen, and we just call that -- we give it this name of this service, and it just generates the empty...

Mat Ryer: It creates an empty service...

Kat Zień: Yeah.

Mat Ryer: I see, okay. [unintelligible 01:00:50.05]

Gautam Rege: So you just have to put in your domain logic?

Kat Zień: You just need to fill in your handlers, your protodefinitions, all of that stuff.

Mark Bates: So I think the answer is "It depends." [laughter]

Liz Rice: I guess that would be fulfilling the same kind of functions that a framework might give you. You have a homegrown project.

Kat Zień: Yeah. To sum up, it's worth doing it once from scratch, so you understand it, because nothing will teach you better than writing a simple context package, or writing a debugger from scratch, or something like this, because that really teaches you...

Mark Bates: But that's a "I'm trying to learn" perspective. For me, as a consultant, as somebody who builds a lot of apps, for me time is of the essence. Just getting to market, getting the thing out. That's when I would absolutely turn to a Buffalo (or previously Rails), where it's just like "Boom!", I can start business logic, somebody else has made all the decisions for me, and I'm good. But just like in Ruby, I would use Sinatra for some really small things where I didn't need a full-blown Rails app, right? And in Go I still turn to the standard library when I just need a small, quick, tight little web app, and I don't need the bells and whistles that comes along with it.

Liz Rice: I think that's true, particularly if you're starting from something that you don't really know where it's going. If you go straight to a framework, you're gonna be locked into the opinions of that frameworks. And if you know that the opinions of that framework meet what you're going to be doing - then great, it is the right tool for the job. And if you haven't figured that out yet, then maybe it's too early to adopt a framework.

Mark Bates: Yeah.

Mat Ryer: That's actually a really good point, because a framework is something else to learn. However simple it is, it is a new thing to learn. And yeah, in the beginning of projects you don't really know ever what you're gonna be doing, I think.

Kat Zień: Yeah, and if you lock yourself into a framework, it's very hard to get yourself out of the framework. After a few years of development it's gonna be very hard to leave that framework. But if you don't have a framework, it's a lot easier to migrate into a framework, I find.

Mat Ryer: Well, I always say "Build small things." And I don't mean therefore don't have big companies, and stuff, but actually - if you can avoid it, don't have big companies. It's way easier... [laughter]

Mark Bates: It really is. Let's try and get another question. I think we've beat web frameworks to death.

Mat Ryer: Ben's winning so far, because he has to [unintelligible 01:03:07.00]

Mark Bates: Dom, who's our next question?

Audience Member: We've got one in the back over there, and then I'll come back to the front.

Mat Ryer: This is for the prize... Is this the last question?

Mark Bates: Alright, here we go.

Audience Member: Hello. Going a bit back to context - it's a quite elegant solution and quite a good way to give timeouts and deadlines for functions; I use it a lot for [unintelligible 01:03:29.25] But the thing that I usually see is most developers never get the context and check if it's [unintelligible 01:03:37.29] They always delegate a third-party library to do the decision. And if the library returns an error, [unintelligible 01:03:45.20] So what do you guys think and how much do you guys look to the context to cancel your code itself?

Mat Ryer: [01:04:02.15] For anyone that didn't hear that, it was talking about the -- a lot of the times you can see context just pass through; the methods themselves that you're writing don't deal with it. I think that's totally legitimate. If you're calling some of the service and it's cancellable, and you're allowing that to be canceled somewhere else upstream, sometimes it's completely appropriate to just pass that straight through and don't touch it. But whenever I'm doing any kind of heavy-lifting, looping around, I will at the top just check. And you can also check the error on a context.

Mark Bates: Yeah, that's one of the four...

Mat Ryer: One of the four methods... And it returns either nil if everything's okay, or a context canceled error. So sometimes you don't have to even use the channel, you can just check that error, and if there's an error, you know the context has been canceled [unintelligible 01:04:51.14]

Mark Bates: Well, by default in the standard library though there are context deadline errors. However, if you implement your own context interface, that error can be anything you want. You can cancel the context with Done, and the error could be "The database doesn't exist." It's not necessarily a cancellation error, is it? You can still cancel it and give a better error, which is very good for goroutines, because it's hard to propagate errors up a lot in goroutines, isn't it?

Mat Ryer: Yeah.

Mark Bates: Unless you use an error group, or something.

Mat Ryer: Right. Yeah, so I think it's okay to just -- if you're not sure, but you know that you're gonna be doing something as part of an HTTP thing, then you could use that context and just pass it through. The request comes with a context, and that does get canceled if they do the Back button, or they refresh, or they close the browser or whatever. Modern browsers will cancel that context. So it is quite cool if you're doing some heavy-lifting and you're doing some work, and you actually kind of bought early and not do any work... It's quite satisfying.

Mark Bates: And clean up all that stuff that maybe got opened, that's no longer useful anymore.

Kat Zień: I'd say it's just a safer habit to have as well, because if you think of the alternative, which is not pass it down - then you're gonna have something downstream that expects that context and assumes that it's the one passed from the top; and then something in the middle, if it starts a new context, then suddenly you lose that and it's a mess.

So I think even if you're not planning to use it, it's just always safer to pass it down, because it saves you refactoring later, and it always ensures that it trickles down, rather than somebody randomly overriding it with ContextBackground, because they haven't had it passed.

Mark Bates: Yeah, and it's a completely new context all of a sudden. You can just keep wrapping -- we were talking about the nodes... You can even wrap smaller, tighter cancellations on bits of it, as opposed to doing the whole thing.

Kat Zień: Yeah. Passing it down won't hurt you, but not passing it can hurt you... So don't not pass it.

Mark Bates: Yeah. Great question. I think we had one more question - is that right, Dom?

Audience Member: We've got two more...

Mark Bates: Two more questions, okay...

Mat Ryer: We still have the plush gopher to give away...

Mark Bates: So none of your questions have been good enough apparently...

Mat Ryer: I think Ben's --

Mark Bates: Which one was Ben's?

Mat Ryer: Serialize you life...

Mark Bates: Yeah, that actually was quite good.

Kat Zień: Yeah, that was cool.

Mat Ryer: To be honest, it's more complex than regex, that question. [laughter]

Mark Bates: Or just parsing the question, yeah. It was a good one. Okay, so we've got two more. The first one -- I don't know where the mic is...

Mat Ryer: I forgot about the captures...

Mark Bates: Speak.

Audience Member: Hello.

Mark Bates: There we go.

Audience Member: So this question is a lot less technical than the others... I read an article earlier and it basically said that the next top five sites for fintech locations will be London, Singapore, Belfast, New York and Dublin. As a local guy myself, in Ireland, I thought it was flattering that Belfast and Dublin got the mention, but I'm skeptical about who had done that research and whether they were from Ireland themselves... What I wanted to ask is, considering Brexit and the implications that could be coming up, luckily for all of us here London is number one... But if you were not able to be present in London and program here, whereabouts in the world would you go to be a Go developer?

Mark Bates: I enjoy Boston, but that's also where I live... [laughter] I don't know, personally I think that you can do the job anywhere; it really doesn't matter. Live where you wanna live.

Kat Zień: [01:08:07.16] I was gonna say, I would encourage looking into remote work if that's your thing. It's not for everyone. Some people like going to the office, and that's completely fine. But if you're not particularly attached to the office, you then have the whole world of companies that you could work for. Especially if you're in a place which doesn't really have many native local companies and you wanna work for Amazing Company X, if they hire remotely, that's your chance.

Gautam Rege: Yeah. In fact, talk to GitLab. GitLab doesn't have an office. I was just talking with somebody earlier... And that's so cool. They have so many people all over the world, but they don't have a single office location. I don't think geography matters anymore.

Liz Rice: I think so, too. My team is remote, and most of the company is based either in Israel or Boston, so I know I'd have a home to go to if I wanted to [unintelligible 01:08:51.00]

Mark Bates: And yet you never come to Boston and visit me.

Liz Rice: I do, I just don't see you. [laughter]

Mark Bates: You're like "I'm there every two weeks, Mark." Thank you, Liz. Yeah, thank you... [laughter]

Mat Ryer: Classic burn.

Mark Bates: It really was a classic burn. That was good. I make an effort to see you every time I'm in London.

Liz Rice: That's very kind, thank you.

Mark Bates: That's also a lie, but that's beside the point... Yeah, so remote -- and we had one more.

Audience Member: Can you hear me?

Mark Bates: Yes.

Audience Member: There we go. I'd like to ask you guys about the singleton pattern. I know it's a very controversial design pattern, and with Go you can sort of implement it using package-level variables... And I've seen it being used mainly when it comes to configuration... For example, using the Viper package. I'd like to hear your thoughts on the singleton patterns - whether it should be used or whether it should not be used.

Mat Ryer: That's a great question, and for me it's "Don't use it." It's as simple as that. And actually, don't use any global state. In fact, maybe even in the next version of Go we get rid of package space, global state altogether. If it's a config, you can just pass a config in. It doesn't have to be a singleton. And it's clearer, I think. It means that the dependency is clear that it's needed... Because if it's global space, anything in that package can access it. So you don't really know the flow of where that thing is being accessed; you'd have to go and find it. Versus if it's passed in, it's a bit more verbose, but it's infinitely clearer... So I probably wouldn't use the singleton pattern.

Gautam Rege: Yeah, I think it does complicate things a lot. Avoid using it, but if it's being used in the package, so be it. But don't try to get around the singleton pattern, or try to break it. Just let it be there.

Mat Ryer: It makes testing harder as well.

Mark Bates: Yeah, it absolutely makes testing harder.

Mat Ryer: Yes. Often in tests you want to try it with a different config in that case, or a different state, and you wanna also be able to run your tests maybe in parallel, or concurrently, and in different orders. And if you've got this state that's sticking around between them, it's kind of awkward, and can create interesting and strange, weird bugs that take a while.

If you avoid global state -- Peter Bourgon said it very well; he said if he had to give five words to a new Go programmer, they would be "Don't use global state." He didn't even use the last word, that's how confident he is that that's right.

Mark Bates: I think it was "Do not...", actually.

Mat Ryer: No, it wasn't. He'd used the contraction. And that's Peter.

Mark Bates: And that's just terrible English as well, right...? Yeah, the only thing I'd say to that is the asterisk of "Unless you need it." [laughter] That is 100% solid advice. Try to avoid it. But like everything in life, sometimes there might be a reason. Everything has a use case, otherwise it wouldn't be a pattern.

Liz Rice: There are some bad patterns...

Mark Bates: [01:12:13.09] Well, I agree... I'm not arguing that you should, until you need it.

Liz Rice: I did lots and lots of live code things where I use global variables because it's convenient for doing things very quickly, on the fly. It's terrible for maintainable code.

Mark Bates: Oh, yeah...

Liz Rice: Global state smells very bad to me.

Mat Ryer: Yeah. The solution to it can be as simple as just having a struct and putting them all in there... Even just doing that really does help. I honestly don't think there's a case where you have to use global state.

Mark Bates: I didn't say there was, I just said you might.

Mat Ryer: Yeah, don't do it until you have to do it.

Mark Bates: Until you have to, yeah. But you can use the singleton pattern inside of a struct, for example. We're talking global state -- we're just assuming that we're doing it at a global level; it doesn't mean you can't use a singleton pattern inside of code, for other reasons.

Mat Ryer: It wouldn't be a singleton pattern then, would it?

Mark Bates: Sure it would.

Mat Ryer: You wouldn't just have one of them...

Mark Bates: No, but you might absolutely do -- if you've got a bunch of data in your struct, and you need to formulate it, and it's big, and expensive, and it's only an operation I'm gonna do once, you'd have a sync.once in your struct; you do it and you would just return the cached value at that point. But it's all it still would contain; it's not global state anymore.

That's what I'm saying - the pattern itself is not bad, it's how we use the pattern that makes it bad. Global state makes the pattern bad. The pattern itself doesn't make the pattern bad.

Mat Ryer: Right.

Mark Bates: You could still use it, but try not to do it globally. There are reasons I use sync.once a lot inside of stuff, and that is a singleton pattern. Sync.once enables singletons. Otherwise we'd never have sync.once, right?

Mat Ryer: Well, no, I use sync.once in places where it's not then a singleton, but... Yeah, I see what you mean.

Mark Bates: But it enables the singleton pattern very well.

Mat Ryer: I guess it does.

Mark Bates: So anyway. Avoid global state - I think we all agree on that. But as a pattern, there are times that you might wanna use it. You might also use factory patterns a lot, on occassion. We don't use them in Go a lot, but Java loves them. They have factories for factories over there. It's amazing what they do.

Mat Ryer: It must be massive.

Mark Bates: It's like a factory-factory service impl. Yeah... I think that's all we've got time for then.

Mat Ryer: I think so. We need to choose a winner of the plush gopher for the best question... I mean, there's a standout winner for me, but - how do we wanna decide this?

Mark Bates: Was it one of mine?

Mat Ryer: No, obviously...

Mark Bates: Oh, okay. I like the "What would a year chapter in your life be?" Do we all agree? That was a good question, wasn't it? Clearly not everybody agrees, but... [crowd applause] There we go. Gautam, let's show them that arm here that the Yankees are trying to recruit you for. Throw that over there to him.

Mat Ryer: Could you throw that over to...?

Mark Bates: Come on, show us that arm. Come on, really wind it up. There you go! If Tom Brady ever runs out of the Patriots, we've gotta recruit you.

Gautam Rege: I just missed, by the way.

Mark Bates: You missed. Oh, then never mind, we're not gonna recruit you. You can go to the Yankees, or a completely different sports team, by the way.

Mat Ryer: Don't forget, it's a podcast.

Gautam Rege: Oh, yeah...

Mat Ryer: You've got it!

Mark Bates: We're gonna CGI it in, and it'll go right into the right place. They don't know, they can't see...

Mat Ryer: I think we have now run out of time, haven't we?

Mark Bates: On GoTime.

Mat Ryer: [01:15:46.21] What an experience this was. Don't forget, this is not just a podcast, this is also an actual, live event in real life, which is this... It's also being live-streamed. There's gonna be a video, there's gonna be a book, we're gonna try to get on Netflix, it's gonna be on the iMacs...

Liz Rice: Can you imagine? You might have to watch this over and over again... [laughter]

Mark Bates: By the way, if you do a live podcast like this, when Mat and I were planning it we may have forgotten to tell the panelists that there was gonna be an audience, and it was gonna be on YouTube. [laughter] So you can only imagine their lovely faces when we told them "Oh, it's gonna be filmed, and live", and Gautam is like "What?!" [laughter]

Kat Zień: Well, I knew...

Gautam Rege: The way I look at it is I think among all the panelists, the people who spoke the most were you both. [laughter] So I enjoyed it!

Mark Bates: Yeah, that's about right, I think...

Mat Ryer: Well, I mean, it's obvious we shouldn't be organizing anything. To the point where it's so obvious it stops being our fault. That's how I think of it.

Mark Bates: I do actually have one question about this... Did people enjoy it? Should we do this again next year? [crowd cheering and applauding] Okay... I like it.

Mat Ryer: Yeah. Well, we should do a proper closing of the show, because podcasts - at some point they have to end.

Kat Zień: [unintelligible 01:17:06.19]

Mat Ryer: No, no, I don't want that.

Mark Bates: Mat and I don't wanna get off stage, because we're not on stage for the rest of the week... Except for when we're on stage, hosting the conference for the rest of the week... So we really like to [unintelligible 01:17:17.23]

Mat Ryer: I'm just trying to be professional, and you keep interrupting me and stopping me from being professional.

Mark Bates: Yeah... Well, Kat, why don't you just close this off?

Kat Zień: Oh. Thank you everyone for coming. We hope you enjoyed this, and see most of you tomorrow!

Mark Bates: Thank you so much!

You can’t perform that action at this time.