LIVE from LondonGophers as part of GopherCon UK! Mat Ryer, and Mark Bates were joined by Liz Rice, Kat Zień, Gautam Rege to talk about the magic in Go’s standard library. Huge thanks to the organizers of LondonGophers and GopherCon UK for making this possible.
Linode – Our cloud server of choice. Deploy a fast, efficient, native SSD cloud server for only $5/month. Get 4 months free using the code
changelog2019. Start your server - head to linode.com/changelog
KubeCon + CloudNativeCon – The Cloud Native Computing Foundation’s flagship Kubernetes community conference which gathers adopters and technologists from leading open source and cloud native communities. Learn more and register — get 10% off with the code
Fastly – Our bandwidth partner. Fastly powers fast, secure, and scalable digital experiences. Move beyond your content delivery network to their powerful edge cloud platform. Learn more at fastly.com.
[crowd applause] Thank you, hello! That was very generous of you, giving that to just me. I really appreciate that.
Yeah, Mat’s gonna edit that in over all his bad jokes later…
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]
…if not, the best in London. I think we can agree on that.
And also, the other voice you can hear is one of the best Mark Bates in the world. [laughter] It’s 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–
That’s actually what I’m the most nervous about. It’s not having the live audience.
So we’ll see if that in any way impacts Mat’s hosting abilities over the next hour.
They can’t get worse.
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.
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]
A round of applause! We can’t do a round of applause on the podcast normally. This is brilliant.
Yeah. Well, we can, it’s just very weak. [laughter] It’s usually just Mat, he tells a joke and he goes [clapping].
To be fair, there are people on Slack clapping with you.
Yeah, that is true. Okay then.
That’s true. Sometimes they miss all the fingers off on the emoji when they clap to me though.
Yeah, just the one. I’ve seen that, too.
Weird. Really strange kind of wave.
Yeah, I get that emoji a lot. It’s weird. It’s one-off, I think.
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]
Gautam, would you like to introduce yourself?
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.
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.
Yeah. I’m much better in text. [laughter]
Gautam, tell us about yourself.
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…
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.
You don’t happen to also maybe run a Go conference in India, do you?
Yeah, actually I’m the organizer for GopherCon India.
Oh, there you go then. So if you wanna go to India…
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…
So it’s hotter than the rest of India.
The problem is a lot of people register for the conference, but don’t attend the conference because they’re at the beach. [laughter]
It’s really on-brand, the place name though… Goa.
Absolutely. Go in Goa.
Yeah, love it.
They couldn’t have it in a place called Javarra…
You know there’s an actual place called Java, that they could have just actually used… [laughter]
I’m much better in text… [laughter]
Again, it’s that single-finger emoji… And in the middle here we have Kat. Kat, say hi.
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.
Fantastic. Do you have a Twitter account that perhaps people can follow?
We do, surprisingly, @londongophers.
Wow, who would have thought…?!
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…?
That’s another one of those names we give Mat.
It’s Kat Zień.
Gets better every time.
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]
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.
It’s an illusion.
I forgot to mention one thing…
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.
And Mat does have a random gift he’s been desperate to give away for some bizarre reason.
A beach towel. From – yeah, the wrong GopherCon.
Yeah. It’s from the other GopherCon, but it’s still a towel. If you like being dry…
Is it unused?
It’s unused, yeah. I hope… It wouldn’t be dry. [laughter]
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.
That’s why it’s soiled, because we sit on soil. [laughter]
This is what happens when we go off-script.
See? Look, now you’re just moaning at us. [laughter]
That’s fine. Moaning is acceptable, because at least you can hear it on the podcast, it backs up the way you are in real life. Otherwise I do think people are gonna question that.
Fair enough. I think we should start.
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.
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 that Ruby.” [laughter] Yeah, so we really are on point with the name of this, absolutely, because none of us know what it is.
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.
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.”
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…
Four, yeah. Because the request param is at the forefront. So yeah, I love it. I use it pretty much daily.
Could you give us an example where you’ve abused it? You’ve done something you probably shouldn’t have with Context?
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]
[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 –
Yeah, which is the context with value, right?
Context with value… They’re sort of hidden dependencies; they can be.
Sideline APIs, they’re often referred to as, yeah.
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.
Yeah, I always say they should be user request-specific.
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.
Yeah, small, specific and constant, and not mission-critical.
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.
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.
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.
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.
Okay, that’s new…
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.
I need to dig up the name.
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.
I’ll do it now. And show notes later.
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.
And would you say you just like the Context package, you love it, or you’re in love with it?
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 or the request 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.
Oh, so they’ve implemented the Context interface itself.
So then you can provide your own context objects like that, can’t you?
And Buffalo does this too, doesn’t it?
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.
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…
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.
Give us an example.
In a command, or something, you mean?
I’m all of those people. [laughter]
…and then you end up doing context.TODO(). [laughter] Just put up a dummy context instead.
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.
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.
Yeah. It’s a user running the CLI, and…
You mean somebody at a CLI typing in a command?
That’s a request…
…and asking you to do something.
I often pass context in as the first value to a new, for example.
Where were you when Dave was having a go at me on Twitter? [laughter] Too little, too late. No, but here’s the thing…
Who trusts what Dave Cheney says, really…? [laughter]
That’s an example of something that might actually get cut out. [laughter]
Everybody right now is tweeting at Dave. “Mark just said “Who is Dave, really?” [laughter]
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.
I think that’s nice.
[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–
I never got that TODO… I actually don’t get that.
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.
If you don’t know what to do, just TODO.
Yeah. If you just can take anything, TODO. Anyway, cancel.
I have actually a question for the panel.
I’ve just canceled the context.
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?
The only reason there’s two is because context came after, and they have the version 1–
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.
Exactly. I’m giving people a treat.
You really are.
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]
But let me ask the question to the panel…
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?
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?
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…
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.
I wouldn’t mind a copy context. IO copy with a context…
Oh yeah, that would be cool.
Someone did write one; there is one that you can use.
Oh, interesting. Okay, I think…
We should move on, because–
Yeah, I’d love to hear some other ones. Gautam, tell us a little bit about your favorite parts of the standard library.
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.
Yeah, we don’t discriminate against the IDEs… Except for TextMate 2, which hasn’t come out yet, so you’re good. [laughter]
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.
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!”
That’s taking laziness to the next level.
Thank you. Thank you.
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.
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 the array back.
Can you give us an example where that’s really helped you in your code? Apart from just simple regular expressions…
Let me think about it…
Yeah, we’ve got time. We’ll wait.
Yeah… So there was a case where we were trying to map out the entire URI, with the username, password, host, port everything together…
So you wanted to write your own URI.parse.
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.
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?
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. It will get you back a hash in a named hash so you can actually process it better.
That is cool. My problem with regex is it’s too easy.
Yeah, that’s everybody’s problem.
I like a challenge. [laughter] It’s like “What? Okay…”
Stack Overflow…! Oh, that’s clearly human-readable. Let’s make it a bit more difficult.
But yeah, once you learn it - of course.
It’s fun, because then you’re not just coding to finish a job, but you’re actually doing it well.
Yeah. You’re casting spells as well, at the same time.
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.”
I was gonna say…
It’s brilliant. Hours of fun.
There’s actually Gobular.com, 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.
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?”
We compile it and we use the regex package, and give you the result… [laughs]
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…
No, because you just give me a string of regex, I run it through compile, and it either compiles or not.
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]
So they’re still like a chicken and egg, because if you just run it through compile, then what checks to compile…?
Well, the Go team… [laughter]
Anyway, anyway… Dead end.
No, but that’s a good point, that Kat brings up - who watches the regex watch people? We may never know.
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.
Yeah. It’s like your last name.
That just doesn’t compile anywhere.
It just doesn’t compile in my brain. Not when I see it written down.
I believe Go does implement Perl-style regex, correct?
I think so, yeah. Not the PHP one, because that never worked.
Yeah. It doesn’t match Ruby’s either. There are a few places where Ruby doesn’t match.
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.
I can’t argue with that.
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.
Question for you - can an alpha cover all the accented characters, and non-roman characters?
Alpha is only for ASCII.
Just ASCII, okay.
That’s the problem with wide characters. If you’re doing wide characters, regular expressions is not a beast.
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?
I think wide UTF8 support is there for regular expressions support already. And I don’t think it gets to UTF8, because then you need to… suppose 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.
My very first professional job was doing double-byte character support in a 3270 emulator, if I remember right. It was horrible.
Now she can write that 3270 emulator in 20 minutes on stage, and for fun. [laughter] She cracks her knuckles, and goes “Hang on…”
I’ll just get my computer our…
Yeah, exactly. She’ll do it for us by the end of the podcast. [laughter]
But Liz, you were mentioning earlier about the io.Reader and io.Writer…
Yeah, so when we were first discussing doing this podcast on this topic of the gold in the 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 –
They’re brilliant, simple interfaces, aren’t they? They’re just so simple and brilliant.
They’re so simple, and they’re so pluggable and so testable… Which is great.
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.
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.
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.
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?
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.
The real magic as well I think is the fact that they’re single-method interfaces.
An interface with one method is so easy to implement. It gets implemented a lot, and this one - that’s a good example 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.
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.
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…
…so 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.
So it has that mechanical sympathy.
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.
Yeah, we should all.
[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.”
Buffalo users, don’t listen to her. [laughter] She doesn’t know what she’s talking about. You need Buffalo.
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.
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.
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…
“How does that work…?”
“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.
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.
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.
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 handler and it returns an error 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]
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.
Tell us about that.. What’s the single reverse proxy?
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 net/http/httputil.NewSingleHostReverseProxy. 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.
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…?”
Yeah, I’ve used it, and I can’t remember what for…
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 HTTP [unintelligible 00:42:56.21] request. 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.
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.
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.
One line of code.
It’s called a Single Reverse Proxy, job done.
“Yeah, I’ll give it my best shot. It might take me a couple of weeks…” [laughter]
Yeah… One line.
That’s what I did… That was my holidays.
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]
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.
Yeah, and you get to use Go code to make these decisions.
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.
I thought you were gonna talk about the Time package. [laughter]
Why? Time is on my side, mate. I don’t need to worry about it. No? Okay, fine. We can cut that out later.
Yeah, don’t worry too much about the time. At some point things will end, and then we will be fine.
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.
Great ideal. Soiled.
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.
Did the take the mic to dinner?
He did! That chewing you hear in the background is Paul.
Let’s just turn it on and see what he’s having. “Hello, we’re going live over to Paul…” [laughter]
I’ve seen they’re livestreaming it… Can’t they just send us some questions from the dinner–
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]
Have you ever used the len operator on a buffered channel, and why?
That came up today, I think in Cory’s… No, because I don’t use buffered channels.
That’s for buffered channels, right?
Okay. Because you can also set the capacity.
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.
Yeah, but you wanna be careful using it, because you’ll probably get an inconsistent result.
Yeah, it’s not safe. And you shouldn’t be using buffered channels, so… [laughter] It’s not a problem.
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.
[unintelligible 00:51:31.16] workerpools just the other week, and that was exactly what I suggested.
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.
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.
[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.
Yeah, that’s good.
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.
There’s a knife fight going to happen over this… Okay, fantastic. Brilliant.
The person with lesser hair wins. [laughter]
Okay, Dom’s got a question over there then…
Can I ask a non-technical question, is that okay?
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.
And 22 is your age, and that’s the chapter…
And every chapter is a year?
That’s a long chapter.
Every chapter in my book is 21. I’m just… [laughter]
So you’re asking us what we’d call the current year of our lives?
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…
Some of us have been at this for 20.
It’s gonna take a while.
It’s gonna take a while… [laughter]
Well, just pick one year… Like, chapter 22 - that’s when you were 22.
Pick one year…
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.
You’re dating yourself… [laughter] Is that like a new app? It’s for people who can’t find love…
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.
Yeah, but why is it not going very well? That’s the thing.
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.
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.
That’s lovely. Do you stay in touch with them?
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.
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.
Yeah… I didn’t give it a name though… I don’t know if I have a name for it.
Don’t worry, we’ll do the names later.
That’s one of those things we can cut out for Gautam now.
We get one cut each. [laughter] You’re allowed to embarrass yourself once.
Mat, you’ve used like ten.
Okay, so are you ready for a question?
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?
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.
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]
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 –
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.
No… That’s the wrong answer.
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.
Or use the solutions that are already built in Go.
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.
What do you mean? How do you describe them, how do you define them?
They are single-responsibility –
Sorry… When you say “Something gets generated”, what does it get generated, and where does it get generated from?
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…
It creates an empty service…
So you just have to put in your domain logic?
You just need to fill in your handlers, your protodefinitions, all of that stuff.
So I think the answer is “It depends.” [laughter]
I guess that would be fulfilling the same kind of functions that a framework might give you. You have a homegrown project.
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…
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.
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.
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.
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.
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]
It really is. Let’s try and get another question. I think we’ve beat web frameworks to death.
Dom, who’s our next question?
We’ve got one in the back over there, and then I’ll come back to the front.
This is for the prize… Is this the last question?
Alright, here we go.
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 HTTP handlers and webservices 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?
[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.
Yeah, that’s one of the four…
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 I think it’ll just return the error.
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?
Unless you use an error group, or something.
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.
And clean up all that stuff that maybe got opened, that’s no longer useful anymore.
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.
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.
Yeah. Passing it down won’t hurt you, but not passing it can hurt you… So don’t not pass it.
Yeah. Great question. I think we had one more question - is that right, Dom?
We’ve got two more…
Two more questions, okay…
We still have the plush gopher to give away…
So none of your questions have been good enough apparently…
I think Ben’s –
Which one was Ben’s?
Serialize you life…
Yeah, that actually was quite good.
Yeah, that was cool.
To be honest, it’s more complex than regex, that question. [laughter]
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…
I forgot about the captures…
There we go.
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?
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.
[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.
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.
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]
And yet you never come to Boston and visit me.
I do, I just don’t see you. [laughter]
You’re like “I’m there every two weeks, Mark.” Thank you, Liz. Yeah, thank you… [laughter]
It really was a classic burn. That was good. I make an effort to see you every time I’m in London.
That’s very kind, thank you.
That’s also a lie, but that’s beside the point… Yeah, so remote – and we had one more.
Can you hear me?
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.
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.
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.
It makes testing harder as well.
Yeah, it absolutely makes testing harder.
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.
I think it was “Do not…”, actually.
No, it wasn’t. He’d used the contraction. And that’s Peter.
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.
There are some bad patterns…
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.
Global state smells very bad to me.
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.
I didn’t say there was, I just said you might.
Yeah, don’t do it until you have to do it.
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.
It wouldn’t be a singleton pattern then, would it?
Sure it would.
You wouldn’t just have one of them…
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.
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?
Well, no, I use sync.Once in places where it’s not then a singleton, but… Yeah, I see what you mean.
But it enables the singleton pattern very well.
I guess it does.
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.
It must be massive.
It’s like a factory-factory service impl. Yeah… I think that’s all we’ve got time for then.
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?
Was it one of mine?
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.
Could you throw that over to…?
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.
I just missed, by the way.
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.
Don’t forget, it’s a podcast.
You’ve got it!
We’re gonna CGI it in, and it’ll go right into the right place. They don’t know, they can’t see…
I think we have now run out of time, haven’t we?
[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 IMAX…
Can you imagine? You might have to watch this over and over again… [laughter]
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]
Well, I knew…
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!
Yeah, that’s about right, I think…
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.
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.
Yeah. Well, we should do a proper closing of the show, because podcasts - at some point they have to end.
No, no, I don’t want that.
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]
I’m just trying to be professional, and you keep interrupting me and stopping me from being professional.
Yeah… Well, Kat, why don’t you just close this off?
Oh. Thank you everyone for coming. We hope you enjoyed this, and see most of you tomorrow!
Thank you so much!
Our transcripts are open source on GitHub. Improvements are welcome. 💚