WEBVTT 00:00.000 --> 00:08.000 Thank you, Maria, for the introduction. 00:08.000 --> 00:10.000 I'm going to get right into it. 00:10.000 --> 00:11.000 System programming. 00:11.000 --> 00:15.000 Lessons from building a networking stack for microcontrollers. 00:15.000 --> 00:18.000 I'm Patricia Wittingslow. 00:18.000 --> 00:25.000 I'm the creative of El Netto, which is the networking stack that runs on these 00:25.000 --> 00:30.000 constrained places with around 20 kilobytes of RAM. 00:30.000 --> 00:34.000 And I'm a technical maintainer, a core maintainer, I'd say. 00:34.000 --> 00:40.000 I teach Go at a university course, embedded systems with biomedicine applications, 00:40.000 --> 00:45.000 and I've also taken consulting up recently. 00:45.000 --> 00:48.000 All right, so this is the agenda for today. 00:48.000 --> 00:54.000 The overarching question I'll try to answer is how Go can be used as a systems programming language. 00:54.000 --> 00:58.000 When so many people say otherwise. 00:58.000 --> 01:02.000 So, let's simple back. 01:02.000 --> 01:05.000 Let's circle back to a simpler time. 01:05.000 --> 01:07.000 I'm lay pain and picture. 01:07.000 --> 01:10.000 It's mid-pandemic, and I'm hold over my desk, 01:10.000 --> 01:15.000 hooking up wires, trying to connect the HTTP to an Arduino. 01:15.000 --> 01:19.000 I've limited memory 32 kilobytes of RAM, 01:19.000 --> 01:24.000 and I'm struggling to fit my CSS classes into the program. 01:24.000 --> 01:29.000 I've decided to use the Arduino IDE for the last time. 01:29.000 --> 01:31.000 There is no slide in. 01:31.000 --> 01:33.000 Oh, yeah. 01:33.000 --> 01:35.000 C++, you later. 01:35.000 --> 01:37.000 No, that's on purpose. 01:37.000 --> 01:38.000 Oh, yes. 01:38.000 --> 01:42.000 It's all part of the... 01:42.000 --> 01:43.000 Part of the... 01:43.000 --> 01:46.000 Yes, suspense. 01:47.000 --> 01:50.000 So, I desperately search on my browser. 01:50.000 --> 01:52.000 Go for Arduino. 01:52.000 --> 01:54.000 Time you go. 01:54.000 --> 01:57.000 It seems a little too good to be true. 01:57.000 --> 01:59.000 So, and it was at the time, 01:59.000 --> 02:02.000 the LVM compiler, which time you go uses, 02:02.000 --> 02:05.000 had series issues when targeting AVR technologies. 02:05.000 --> 02:10.000 By chance, I had found time you go at the dawn of a golden age. 02:10.000 --> 02:15.000 Soon after trying to put it to work for the first time and running into issues, 02:15.000 --> 02:21.000 these issues were to be fixed by the LLVM team. 02:21.000 --> 02:26.000 And I'd host my... Oh, this one should have a video, but... 02:26.000 --> 02:28.000 Oh, it's... 02:28.000 --> 02:29.000 That's... 02:29.000 --> 02:31.000 But I think that's my fault. 02:31.000 --> 02:35.000 Because Google sheet... 02:35.000 --> 02:37.000 Oh, yeah, let's... 02:39.000 --> 02:41.000 Oh, snap. 02:46.000 --> 02:48.000 It's a screenshot they're saying here. 02:48.000 --> 02:51.000 No, I can assure you it's not a screenshot. 02:51.000 --> 02:52.000 Okay. 02:52.000 --> 02:56.000 You're going to have to believe me that there's a video of... 02:56.000 --> 02:57.000 Of... 02:57.000 --> 02:58.000 Arduino... 02:58.000 --> 03:01.000 ...hoking up the HTTP. 03:01.000 --> 03:05.000 And we're getting an LED light to blink. 03:05.000 --> 03:06.000 So, yeah. 03:06.000 --> 03:08.000 Let's hear for the Arduino. 03:08.000 --> 03:14.000 All right, let me actually get the presenter view back on. 03:14.000 --> 03:18.000 And soon after, we got that... 03:18.000 --> 03:22.000 Arduino, you know, the blink. 03:22.000 --> 03:27.000 Oh, and the CSS was terrible. 03:27.000 --> 03:31.000 Just imagine terrible CSS. 03:31.000 --> 03:41.000 So, that was the first attempt at a networking stack I did 4.5 years ago. 03:41.000 --> 03:43.000 That's ether switch. 03:43.000 --> 03:46.000 Second attempt was seeks. 03:46.000 --> 03:49.000 Featured in the book, gained a lot of users. 03:49.000 --> 03:53.000 Book kind of tiny go networking at a low level in the... 03:53.000 --> 03:56.000 In the line light, as far as to say. 03:56.000 --> 03:58.000 And the next generation stack, Alnetto. 03:58.000 --> 04:00.000 That's the one we're working on today. 04:00.000 --> 04:04.000 And the rest assured, Alnetto is likely definitive. 04:04.000 --> 04:07.000 And the first... 04:07.000 --> 04:10.000 Let me show you Alnetto in action. 04:10.000 --> 04:16.000 And let's hope that the gods of the live-coding demos come up... 04:16.000 --> 04:17.000 ...company us. 04:17.000 --> 04:19.000 So, I've already loaded the program into this... 04:19.000 --> 04:22.000 ...CYW449. 04:22.000 --> 04:24.000 Since the... 04:24.000 --> 04:27.000 ...fastem network is kind of spotty. 04:27.000 --> 04:28.000 I've... 04:28.000 --> 04:29.000 I'm... 04:29.000 --> 04:31.000 ...all my hotspot. 04:31.000 --> 04:33.000 Yes, it's on. 04:33.000 --> 04:34.000 My hotspot is on. 04:34.000 --> 04:37.000 You're going to go ahead and plug it in. 04:37.000 --> 04:39.000 All right. 04:40.000 --> 04:42.000 And... 04:42.000 --> 04:45.000 So, I got here a website. 04:45.000 --> 04:46.000 And you can't really see it. 04:46.000 --> 04:47.000 I'm sorry. 04:47.000 --> 04:50.000 I can't get to work for my laptop. 04:50.000 --> 04:51.000 But I'm the person spotten. 04:51.000 --> 04:52.000 And really hope that... 04:52.000 --> 04:53.000 Oh, there you go. 04:53.000 --> 04:55.000 The LED's starting on. 04:55.000 --> 05:00.000 All right. 05:00.000 --> 05:03.000 You get in that camera, a guy, person. 05:03.000 --> 05:05.000 And it's not turning on. 05:05.000 --> 05:06.000 No. 05:06.000 --> 05:07.000 It's still turning on. 05:07.000 --> 05:08.000 So, success. 05:08.000 --> 05:09.000 Can you... 05:09.000 --> 05:10.000 You can all see it, right? 05:10.000 --> 05:12.000 Can I get a yes from the audience? 05:12.000 --> 05:13.000 Yes. 05:13.000 --> 05:14.000 All right. 05:14.000 --> 05:16.000 Yes. 05:16.000 --> 05:17.000 All right. 05:17.000 --> 05:20.000 Feeling good. 05:20.000 --> 05:23.000 So, that's doing DHCP. 05:23.000 --> 05:26.000 And then hosting on the HTTP server, 05:26.000 --> 05:29.000 which you see on my phone screen. 05:29.000 --> 05:32.000 Now, my laptop screen. 05:32.000 --> 05:37.000 So, today, there's no other way to run a fully-fledged networking stack... 05:37.000 --> 05:41.000 on a microcontroller, other than with El Neto. 05:41.000 --> 05:49.000 So, I think it'd be interesting to take a look at how we've got to hear. 05:49.000 --> 05:52.000 Let's take a look at Ether Switch's design. 05:52.000 --> 05:59.000 So, Ether Switch implemented these protocols from EtherNet up to HTTP. 05:59.000 --> 06:05.000 And this was the first interface I came up with that drove the core idea of the networking stack. 06:05.000 --> 06:08.000 Now, any reasonable person would look at that and say, 06:08.000 --> 06:11.000 that seems reasonable enough. 06:11.000 --> 06:14.000 That's because the reasonable person doesn't... 06:14.000 --> 06:16.000 Didn't audit the code. 06:16.000 --> 06:18.000 They don't know how I'm using this. 06:18.000 --> 06:22.000 You see, a TCP connection would load the entire packet into memory. 06:22.000 --> 06:25.000 And enter a loop that would call an update function. 06:25.000 --> 06:28.000 That returned a new update function that was to be called. 06:28.000 --> 06:33.000 Over and over until the packet was completed coded. 06:34.000 --> 06:38.000 And the response also encoded. 06:38.000 --> 06:41.000 And so, you might know there's something like, 06:41.000 --> 06:44.000 to emit data, you needed to receive a packet. 06:44.000 --> 06:49.000 To illustrate, if you, for some reason, need to send out two packets 06:49.000 --> 06:53.000 after receiving a single packet, you wouldn't. 06:53.000 --> 06:56.000 Won't packet in, won't packet out. 06:56.000 --> 06:58.000 Then's the rules. 06:58.000 --> 07:01.000 And this barely worked for an HTTP server. 07:02.000 --> 07:07.000 An HTTP client on the other hand was out of the design scope entirely. 07:07.000 --> 07:09.000 Now, this design was not by accident. 07:09.000 --> 07:13.000 Turns out this shallow function calling would save on stack memory, 07:13.000 --> 07:17.000 which was very limited on the Arduino Uno at that time. 07:17.000 --> 07:21.000 Also, the one in one out decision was on purpose. 07:21.000 --> 07:24.000 It effectively made the TCP stack stateless. 07:24.000 --> 07:28.000 So, a lot of simplicity gains right there. 07:28.000 --> 07:32.000 So, we have to keep track of accuracy numbers. 07:32.000 --> 07:38.000 And the cost, 100% pedigree on maintainable code. 07:38.000 --> 07:43.000 It may be the lightest on memory HTTP server in the world, 07:43.000 --> 07:46.000 but we don't speak of others switch anymore. 07:46.000 --> 07:49.000 All because I want to fit in those CSS styles. 07:49.000 --> 07:52.000 Can you believe it? 07:52.000 --> 07:55.000 But, you know, it did get some more CSS styles 07:55.000 --> 07:56.000 for the Arduino library. 07:56.000 --> 07:57.000 Let me in on. 07:57.000 --> 07:59.000 So, some ones. 07:59.000 --> 08:03.000 Next up, six. 08:03.000 --> 08:07.000 And, or six, depending on your pruditionist. 08:07.000 --> 08:10.000 It's supported NTP, DNS IPv6. 08:10.000 --> 08:13.000 Got some, got something going on for it, you know. 08:13.000 --> 08:16.000 And more support. 08:16.000 --> 08:20.000 And with six came improvement. 08:20.000 --> 08:23.000 The use of a singular is no accident. 08:23.000 --> 08:28.000 Behold, my greatest failure to the go community. 08:28.000 --> 08:31.000 I had spent another year and a half on the network in stack. 08:31.000 --> 08:36.000 And all I could show for it was that I could now send a packet whenever I wanted. 08:36.000 --> 08:39.000 I didn't have to wait for a packet. 08:39.000 --> 08:43.000 And I could send two packets now, not just one. 08:43.000 --> 08:45.000 And it's, in spite of its shortcomings, 08:45.000 --> 08:48.000 seeks brought with it something new. 08:49.000 --> 08:53.000 A became an overnight success in the embedded go community. 08:53.000 --> 08:56.000 Since it was the only networking stack that enabled 08:56.000 --> 09:00.000 the internet access on the Raspberry Pi Pickle W, people started using it. 09:00.000 --> 09:04.000 And it's even covered in the book, home automation and go. 09:04.000 --> 09:06.000 Seeing them now, people depended on it. 09:06.000 --> 09:10.000 And how six was quite hard to maintain. 09:10.000 --> 09:15.000 I set out to design a new networking stack. 09:16.000 --> 09:18.000 So in comes El Neto. 09:18.000 --> 09:21.000 El Neto, now has IGMP. 09:21.000 --> 09:25.000 Has everything either switch and six has plus ICMP, 09:25.000 --> 09:29.000 IGMP and RMI. 09:29.000 --> 09:37.000 And we can now, oh, and now this is the interface. 09:37.000 --> 09:39.000 El Neto uses. 09:39.000 --> 09:43.000 As you can tell, like it's very, 09:44.000 --> 09:47.000 it's based off of go primitive types. 09:47.000 --> 09:52.000 Very simple, very easy to implement a stack or a node in El Neto. 09:52.000 --> 09:54.000 And it's very maintainable. 09:54.000 --> 09:59.000 And this right here, this, I believe, is the forever stack. 09:59.000 --> 10:01.000 El Neto was here to stay. 10:01.000 --> 10:04.000 It's a maintainer's dream come true. 10:04.000 --> 10:07.000 El Neto gives me peace of mind that we'll be able to continue 10:07.000 --> 10:12.000 development many years in the future without having to rewrite again. 10:12.000 --> 10:16.000 It's, and it's so maintainable, like you wouldn't even believe. 10:16.000 --> 10:20.000 We didn't, and we didn't lose a valuable feature. 10:20.000 --> 10:26.000 We don't need to, like, wait for a packet to send packet. 10:26.000 --> 10:30.000 And El Neto would not be possible without its less glamorous cousin 10:30.000 --> 10:33.000 that device driver. 10:33.000 --> 10:38.000 We got three networking drivers that work with El Neto, currently. 10:38.000 --> 10:41.000 And we support most of the bells and whistles. 10:41.000 --> 10:43.000 Not on all platforms. 10:43.000 --> 10:47.000 But 10 megabit internet, 100 megabit internet, you're good. 10:47.000 --> 10:52.000 And gigabit internet, soon to come. 10:52.000 --> 10:55.000 So, maybe you'd guess. 10:55.000 --> 11:00.000 There's lots of lessons to be learned from building three networking stacks. 11:00.000 --> 11:03.000 I know I learned a couple at least. 11:03.000 --> 11:06.000 The lessons we'll show you now. 11:06.000 --> 11:08.000 I wish to show you, if you so let me. 11:08.000 --> 11:12.000 Or that are co-ocoded and she coded. 11:12.000 --> 11:14.000 So, green to black diamonds. 11:14.000 --> 11:18.000 The green circle is, hey, this will probably be useful for you. 11:18.000 --> 11:21.000 Just any developer out there, and the black diamond is, hey. 11:21.000 --> 11:25.000 This is a very niche use case situation pattern. 11:25.000 --> 11:29.000 First up, who cares about heap allocations here? 11:29.000 --> 11:30.000 Show of hands? 11:30.000 --> 11:31.000 Okay. 11:31.000 --> 11:34.000 I was expecting much less hands. 11:34.000 --> 11:37.000 I'd be suspicious of these people, right here you say. 11:38.000 --> 11:42.000 Truth is, if you're using go in the, like, just normal go, 11:42.000 --> 11:44.000 there's not much reason to care about heap allocations. 11:44.000 --> 11:46.000 The go GC is amazing. 11:46.000 --> 11:50.000 As you might have learned in Hesus's earlier talk. 11:50.000 --> 11:53.000 And it's constantly evolving and improving. 11:53.000 --> 11:56.000 On the other hand, I'd say I'd need to care. 11:56.000 --> 11:59.000 That's what can process hundreds of packets of second 11:59.000 --> 12:03.000 on these microcontrollers with very limited memory. 12:03.000 --> 12:06.000 And the tiny go GC is not the same as a go GC. 12:06.000 --> 12:08.000 And it has some rough edges. 12:08.000 --> 12:12.000 So, if I just allocate a single byte on every packet, 12:12.000 --> 12:15.000 eventually this program can event, like, 12:15.000 --> 12:20.000 crash and take down my user's entire computer, 12:20.000 --> 12:23.000 not just the program. 12:23.000 --> 12:27.000 So, I need to care. 12:27.000 --> 12:32.000 Maybe I can refresh this because making it a heapless means 12:32.000 --> 12:34.000 removing all heap allocations. 12:34.000 --> 12:37.000 Let's refresh, so it's something we can all think home. 12:37.000 --> 12:42.000 I call it mechanical sympathy regarding heap allocations. 12:42.000 --> 12:45.000 So, why have I listed this? 12:45.000 --> 12:48.000 Well, it just requires a little bit of training. 12:48.000 --> 12:53.000 I think that with knowing 20% of the places, the go GC allocates, 12:53.000 --> 12:56.000 you can eliminate 80% of heap allocations. 12:56.000 --> 12:59.000 And I think there's, um, 12:59.000 --> 13:02.000 and there's a good example I got here for you, 13:02.000 --> 13:05.000 to be risking your libraries. 13:05.000 --> 13:08.000 Right here, I don't know, you probably can't see this, 13:08.000 --> 13:14.000 but I've designed an interface for a decoder 13:14.000 --> 13:18.000 in, for a MQTT protocol. 13:18.000 --> 13:20.000 MQTT is like HTTP. 13:20.000 --> 13:22.000 So, if you're not familiar with the MQTT, 13:22.000 --> 13:24.000 think of HTTP. 13:24.000 --> 13:29.000 And the MQTT protocol has strings that are processed 13:29.000 --> 13:31.000 and then given to the user. 13:32.000 --> 13:34.000 And these strings are unbounded. 13:34.000 --> 13:36.000 They can be very large in size. 13:36.000 --> 13:39.000 And I purposefully designed some, like, 13:39.000 --> 13:42.000 this decoder interface that heap allocates these strings 13:42.000 --> 13:44.000 to then give them to the user. 13:44.000 --> 13:49.000 And my implementation I provide in the library is memory limited. 13:49.000 --> 13:53.000 So, it's not going to allocate an arbitrary-sized string, 13:53.000 --> 13:56.000 an arbitrary number of strings. 13:56.000 --> 13:59.000 It will fill its buffer up, 13:59.000 --> 14:01.000 and then just error out. 14:01.000 --> 14:05.000 So, this gives you peace of mind being a library developer. 14:05.000 --> 14:08.000 You don't have to worry about making your implementation 14:08.000 --> 14:10.000 super-secure, um, 14:10.000 --> 14:15.000 performance in the face of gigabyte-sized MQTT messages. 14:15.000 --> 14:17.000 You can just provide the user with, like, 14:17.000 --> 14:19.000 here's a, here's an interface. 14:19.000 --> 14:21.000 If you care about gigabyte-sized messages, 14:21.000 --> 14:23.000 implement the interface for your use case. 14:23.000 --> 14:26.000 I'm going to provide a constrained size, 14:26.000 --> 14:28.000 very simple implementation. 14:28.000 --> 14:31.000 And my library, otherwise, 14:31.000 --> 14:33.000 does no heap allocations. 14:33.000 --> 14:36.000 So, you avoid CDs, basically, 14:36.000 --> 14:38.000 by using this pattern. 14:38.000 --> 14:41.000 Work smarts, not hard. 14:41.000 --> 14:45.000 Next up, avoid global-meatable states. 14:45.000 --> 14:49.000 Outside of package main, but you didn't hear that. 14:49.000 --> 14:56.000 The go-standard library embraces global-meatable state in several cases. 14:56.000 --> 14:58.000 The math-brand is part of most famous. 14:58.000 --> 15:00.000 You're aware of, you know, 15:00.000 --> 15:01.000 math-brand V2. 15:01.000 --> 15:04.000 They're kind of regretting that decision. 15:04.000 --> 15:05.000 Just don't do it. 15:05.000 --> 15:06.000 The fix is that simple. 15:06.000 --> 15:08.000 Identify your day of structures. 15:08.000 --> 15:12.000 And add a method or kind of package that as an argument 15:12.000 --> 15:14.000 to your functions. 15:14.000 --> 15:16.000 Here's an example. 15:16.000 --> 15:21.000 The second most used library in the go-eco system, 15:21.000 --> 15:23.000 Google UUID. 15:23.000 --> 15:27.000 It uses a global variable when you call new random, 15:27.000 --> 15:28.000 called the render. 15:28.000 --> 15:30.000 Just extract it. 15:30.000 --> 15:32.000 Make a generator type. 15:32.000 --> 15:36.000 The user can provide the random source with it. 15:36.000 --> 15:41.000 And you can add all the config you want to this generator. 15:41.000 --> 15:44.000 And it also simplifies your outward-facing API. 15:44.000 --> 15:47.000 Now, you don't have new random before, 15:47.000 --> 15:50.000 new random V5, new random with hash. 15:50.000 --> 15:55.000 You can just put that all into the configuration aspect. 15:55.000 --> 16:00.000 So, to me, this feels like a no-brainer improvement. 16:00.000 --> 16:02.000 You're welcome, Google. 16:02.000 --> 16:03.000 If you're here. 16:03.000 --> 16:06.000 And for this one, let's jump straight into the example, 16:06.000 --> 16:09.000 Composing Strucks with non-pointed types. 16:09.000 --> 16:14.000 All you need to know is that this is like a moushka. 16:14.000 --> 16:18.000 This is a code taken out of Lnetto. 16:18.000 --> 16:21.000 You have like the sense-based, the control block, the handler, 16:21.000 --> 16:23.000 the con, the TCP pool. 16:23.000 --> 16:25.000 It's all like TCP's day-to-day structures. 16:25.000 --> 16:27.000 And they're all like moushka into each other. 16:27.000 --> 16:31.000 And tell me, does anyone see a pointer in there? 16:31.000 --> 16:33.000 Maybe I'm hiding one behind value? 16:33.000 --> 16:37.000 Well, the truth is, oh, yeah, there's a slice in there. 16:37.000 --> 16:40.000 But no, you're too smart for your own good. 16:40.000 --> 16:43.000 Yes, there is a slice. 16:43.000 --> 16:45.000 Is there any other slice? 16:45.000 --> 16:46.000 Oh, yeah. 16:46.000 --> 16:50.000 But data structures, like Strucks. 16:50.000 --> 16:52.000 I mean, avoid a pointer if you can at all. 16:52.000 --> 16:57.000 This doesn't work when you have types that share internal data. 16:57.000 --> 17:02.000 Like TCP pool is something I actually create an instance 17:02.000 --> 17:04.000 as with a new constructor. 17:04.000 --> 17:09.000 We can avoid using a new constructor, try using like reset 17:09.000 --> 17:10.000 or configure methods. 17:10.000 --> 17:14.000 And declaring your struct with a bar. 17:14.000 --> 17:18.000 The bar keyword, name of your variable, Strucks type. 17:18.000 --> 17:23.000 I found this to simplify the API a lot. 17:23.000 --> 17:27.000 And you also avoid nil pointers, which is like something 17:27.000 --> 17:31.000 people throw love, do do at go for. 17:31.000 --> 17:36.000 Because nil pointer dereferences are like a risk in go. 17:36.000 --> 17:41.000 And also, I'm not sure if that second example is always 17:41.000 --> 17:43.000 viable, like valid. 17:43.000 --> 17:47.000 If someone's familiar with go and can tell me, if I can assure that I 17:47.000 --> 17:50.000 call, if I'm locked, when enter reset. 17:50.000 --> 17:53.000 If that's valid, I'd be welcome. 17:53.000 --> 17:55.000 I think it's valid, but I might not. 17:55.000 --> 17:59.000 Take, just make, throw a check on that second example. 17:59.000 --> 18:01.000 All right. 18:01.000 --> 18:04.000 This one is very, there's a simple one. 18:04.000 --> 18:06.000 Build code around primitive interfaces. 18:06.000 --> 18:11.000 It's also very hard to explain. 18:11.000 --> 18:12.000 There's a lot of hand waving. 18:12.000 --> 18:15.000 I feel it's sort of an art. 18:15.000 --> 18:20.000 All I can say is make your interfaces as simple as possible 18:20.000 --> 18:21.000 and no simpler. 18:21.000 --> 18:24.000 Sounds sort of pithy and meaningless. 18:24.000 --> 18:28.000 But I feel like unless you're really, really good. 18:28.000 --> 18:30.000 And I mean top go for it. 18:30.000 --> 18:33.000 You won't get your interfaces right this first time. 18:33.000 --> 18:42.000 Unless you're very familiar with the problem you're solving. 18:42.000 --> 18:46.000 I've recently started the image processing library. 18:46.000 --> 18:47.000 So the developing it. 18:47.000 --> 18:50.000 And I'm sure I got the interface wrong. 18:50.000 --> 18:51.000 Absolutely. 18:51.000 --> 18:55.000 And I'll get it wrong a second time. 18:55.000 --> 18:59.000 And if you got suggestions, if you're familiar with the image processing 18:59.000 --> 19:04.000 at a low level, I'd welcome suggestions on this interface I'm designing. 19:04.000 --> 19:06.000 Make this zero value useful. 19:06.000 --> 19:09.000 And this is a Rob Pike quote. 19:09.000 --> 19:14.000 This one you should be familiar with because it's one of the go-proverbs. 19:14.000 --> 19:18.000 And why am I mentioning it at Boston? 19:18.000 --> 19:22.000 So if it's something we all have heard before. 19:22.000 --> 19:26.000 We've all seen that 2017, 15-ish talk. 19:26.000 --> 19:29.000 Well, I feel it's not heated enough from my experience. 19:29.000 --> 19:33.000 And I think there's also like a little. 19:33.000 --> 19:40.000 I don't see it being used that often in enums as I use it. 19:40.000 --> 19:44.000 Here's examples of how I use it in the networking stack. 19:44.000 --> 19:47.000 The first case is state TCP closed. 19:47.000 --> 19:52.000 The RFC for TCP defines the TCP program. 19:52.000 --> 19:56.000 It defines that the closed state is an invalid state. 19:56.000 --> 19:57.000 It's pre-initialization. 19:57.000 --> 20:03.000 So it's a perfect case to have as a zero value for your enum of states. 20:03.000 --> 20:08.000 The HTTP on the other end does not have a state for the pre-initialization. 20:08.000 --> 20:11.000 For when your DHCP client is like an invalid state. 20:11.000 --> 20:15.000 So I use the empty identifier. 20:15.000 --> 20:17.000 I discard that name space. 20:17.000 --> 20:20.000 I don't have a namespace for the DHCP state. 20:20.000 --> 20:25.000 And I recognize it as being an invalid state. 20:25.000 --> 20:31.000 Finally, when we configure Wi-Fi on this guy, which I just showed you. 20:31.000 --> 20:34.000 And just put the test. 20:34.000 --> 20:40.000 I define the undefined join-off enum value. 20:40.000 --> 20:45.000 And when the user does not set it, set it in the config struct. 20:45.000 --> 20:47.000 I know that it's undefined. 20:47.000 --> 20:51.000 And I can make decisions based on other parameters in the config struct. 20:51.000 --> 20:55.000 So if the user set a password, I'm pretty sure they're going to be 20:55.000 --> 20:57.000 1ing WPA2 security. 20:57.000 --> 21:01.000 If they have no password sets, pretty sure they're joining an open network. 21:01.000 --> 21:04.000 Like the ones we have here at Faustum. 21:04.000 --> 21:08.000 Synchronous API, concurrent package main. 21:08.000 --> 21:11.000 Here's one I strongly suggest you follow. 21:11.000 --> 21:18.000 Just make your API synchronous and create go routines in your package main. 21:18.000 --> 21:25.000 Just avoid these three keywords in your third-party package is my suggestion. 21:25.000 --> 21:31.000 Of course, there are use cases where maybe you're designing machine learning library. 21:31.000 --> 21:34.000 And you want to parallelize certain processes. 21:34.000 --> 21:38.000 And there's a very clear cut use case for it, then go for it. 21:38.000 --> 21:42.000 Overall, if you're doing low-level stuff, I do low-level stuff in tiny go. 21:42.000 --> 21:46.000 I always avoid these keywords in my third-party packages. 21:46.000 --> 21:50.000 And then use them in package main. 21:50.000 --> 21:53.000 And test-driven development. 21:53.000 --> 21:56.000 This might get some drones. 21:56.000 --> 21:58.000 TDD is like a contentious topic. 21:58.000 --> 22:01.000 Note the qualifier, well-known problems. 22:01.000 --> 22:07.000 Now working stacks, lectures, parsers, other well-study topics are well-suited 22:07.000 --> 22:10.000 for TDD. 22:10.000 --> 22:14.000 When you're input and output are known exactly down to the byte, 22:14.000 --> 22:18.000 TDD has been the most effective way for me to develop. 22:18.000 --> 22:24.000 Especially now, we have these AI agents that can generate these tests automatically for you. 22:24.000 --> 22:27.000 So, that's up from that one. 22:27.000 --> 22:29.000 Lastly, internal logging packages. 22:29.000 --> 22:33.000 This sounds like a specific pattern I feel could be generalized. 22:33.000 --> 22:37.000 I've used it for logging packages exclusively. 22:37.000 --> 22:42.000 So it consists of making the API the logger used for your project internal. 22:42.000 --> 22:48.000 Basically, hey, I do accept a slog logger from the user, which is like a standard library. 22:48.000 --> 22:54.000 But then I use an internal package for logging in my whole third-party package. 22:54.000 --> 22:57.000 And I'm going to skip ahead now. 22:57.000 --> 23:02.000 It lets you do stuff like, hey, I may not want to compile my project. 23:02.000 --> 23:05.000 Without the logging entirely, easy to do that. 23:05.000 --> 23:10.000 And also add special logger to your logger, like, 23:10.000 --> 23:13.000 printing all the heap allocations every time you see a diff in heap allocations. 23:13.000 --> 23:17.000 That's use case I found tremendously useful. 23:17.000 --> 23:24.000 And this, my friends, is a story for another Boston. 23:24.000 --> 23:27.000 Well, what do you all think? 23:28.000 --> 23:31.000 I mean, it feels like a bit too simple to be systems programming. 23:31.000 --> 23:35.000 Maybe you're expecting a guide of how to implement lifetimes and go. 23:35.000 --> 23:38.000 That'd be pretty sweet, but we won't solve most of my problems in El Nato. 23:38.000 --> 23:42.000 Or maybe you'd be hoping that the final screen would be a prompt. 23:42.000 --> 23:44.000 The prompt I used to vibe code El Nato. 23:44.000 --> 23:47.000 Quality is pretty good, but not quite there yet. 23:47.000 --> 23:50.000 And the answer is unsatisfyingly simple. 23:50.000 --> 23:53.000 Go is a systems programming language. 23:53.000 --> 23:56.000 You can write the drivers for the network interface. 23:56.000 --> 24:00.000 And then you can write the networking stack that uses the drivers to send the packets. 24:00.000 --> 24:04.000 And finally, the operating system, which handled the networking stacks. 24:04.000 --> 24:08.000 And if you follow these guidelines, I think it will be better off. 24:08.000 --> 24:10.000 That's all. 24:10.000 --> 24:11.000 Thank you. 24:11.000 --> 24:12.000 Thank you. 24:18.000 --> 24:23.000 And thank you for my cousin for letting me stay in her apartment this week. 24:23.000 --> 24:25.000 Thank you for the free rents. 24:25.000 --> 24:26.000 Thank you.