Check out a free preview of the full Polyglot Programming: TypeScript, Go, & Rust course
The "Projector Operations in Go" Lesson is part of the full, Polyglot Programming: TypeScript, Go, & Rust course featured in this preview video. Here's what you'd learn in this lesson:
ThePrimeagen walks through implementing the SetValue, RemoveValue, NewProjector, and defaultProjector for the Go version of the Projector CLI. The NewProjector function uses the package os to interface with operating system functionality.
Transcript from the "Projector Operations in Go" Lesson
[00:00:00]
>> So let's keep on going. Let's do a little func (p projector) and do set up. Let me put this in the middle for you and do SetValue. So I'm trying to keep the names the same. So I'm gonna keep on using remove value at the end. And these of course are gonna be very easy.
[00:00:14]
So let's go set value string. One nice part about Go, I mean, I don't know if it's really that great. But if you have multiple arguments of the same type, you can just save the type to the end. So you don't have to be like key string value, string this, string that, string, you can just go [INAUDIBLE] string.
[00:00:31]
Makes it really nice. Nice to let you know. Well, nice little shorthand right there. All right, so we're gonna set the value. All we need to do is go if, let's see, we're gonna see, how do we wanna approach this? Well, we have a couple of ways we can approach this.
[00:00:45]
We can do, ok := p.data.Projector, and then we can use p.config.present working directory. And we can say if it's not okay, what do we do here? Or if it's not okay, we need to do something, right? We need to actually set this value in. So, I can go p.data.Projector[p.config.Pwd] but at that point I've probably done it too many times I want to go present working directory equals p.config.Pwd.
[00:01:18]
Boom, go over here see in there present working directory. And we'll set it to a new map[string]string. All right, that looks pretty good, correct. Awesome. And I use the semicolon, so we won't do that. And we have to do two write those two effectively denote creating the object, but there's nothing inside the object.
[00:01:42]
Awesome, so at that point we can just yank this beautiful piece of code, and go [pwd] [key] = value, and we're done with setting the value. So not much more code than typescript actually pretty similar code I'd say to TypeScript. And let's do the exact same thing for deleting.
[00:02:02]
RemoveValue should just have a key string. That is it. We should be able to do the exact same check. We grab out the present working directory. And then we have a dir, right, because at this point we only do something if it exists not the other way around.
[00:02:20]
So I'm gonna delete out that line, bring this thing back up in here and call the delete method. So the delete method is just like the append method. It's one of these magic methods that exist and as you can see right on there, it takes the map that you're gonna be deleting on and the key you wish to delete.
[00:02:36]
So slightly different than TypeScript, TypeScript you actually access the key and then you delete the entry whereas this one you just say the key and it deletes the entry. Awesome. So let's go all the way up to here and just go key. And there we go. We pretty much have the whole thing right there.
[00:02:54]
We use the dir, we use the return value. We have everything, it's looking good, which means we should be able to test all of this. One thing we haven't done yet, is do the from file operation. So we will probably do that now. Now remember the from file operation wants to throw zero errors.
[00:03:10]
We just simply want to return a projector because if the config doesn't exist that's okay. If it's bad JSON we've already decided that's okay. We're just gonna have no errors at all. So let's do that now while we're kind of already here and then we'll go to testing.
[00:03:27]
All right, we're gonna go like this, NewProjector and of course we need to take in a config that is a config, correct? We need to return out, so I can read my mind a pointer to a projector, correct? Awesome, we don't need to worry about an error in this case because we've already decided no errors.
[00:03:45]
So we'll do the exact same thing we need to check, does the config file exists or have you handed me a path to a config that does not exist yet, right? That is a possibility, because the first time you run projector there's just no config file, it just hasn't happened yet.
[00:03:59]
So we'll go like this, now this is where it gets a little more tricky if you will. We can use the fs package and we have to effectively come up with the equivalent of fs exists. So let's do that. And so what they have I believe this one is it Stat, yep.
[00:04:15]
So Stat will give you the Stat about a file, we're gonna do that. And of course what does it return? It returns two item, the FileInfo and an error. If the error is a not found error then we have no file. So let's do all this fun stuff, right?
[00:04:32]
So we'll go like this. We'll go. We don't care about the Stat object because we don't need it. We only need the error. If there is an error while stating then we have ourselves a problem. So we'll use that. And we'll go like this err does not equal nil, is like a classic blunder right there.
[00:04:49]
So use os, not fs map. Got me so good. There we go. So we're gonna do that. We're gonna just simply get the error, make sure that there's no error. And if that's the case, our file does exist. Let's read it the file, and then let's JSON parse the file and then let's return a projector if all that is successful.
[00:05:11]
So this is gonna be a few more steps, I think than the normal one. So let's first go. If, we can erase this. And so we have to read the file, right? So again, how much do you wanna bet it's on the os. We can go os, look at that, read file, it just simply reads the name of the file and returns the contents.
[00:05:32]
So it's just gonna read the whole file, that's the one we need, we don't need any sort of reader in, we don't need to do anything hyper efficient here because it's just not a program that's based on performance. So there we go. Let's read the file, go config.Config.
[00:05:46]
Awesome. And this is gonna return of course the contents and an error, correct. Great. So if there is an error, we need to do something, right? We can't return nil because well we don't wanna return that. So what we're going to do here is, I'm gonna add a nice little convenient function right here called defaultProjector, we'll do it a little bit differently than we did it before.
[00:06:08]
That's gonna return a projector that's just the empty projector, right, it doesn't have a lot. And so we only need to take in a config and that is it. So I'll return &Projector and of course we'll have config: config, we'll do a data of Projector, that is gonna be a map[string] map[string] string.
[00:06:38]
You're also supposed to go string whenever you do that it really does help program go effectively. It's a part of the effective Go book too. So let's hop on our projector because obviously what did I do here I made config a non pointer we're parsing in a pointer.
[00:06:54]
Let's just go over here and just make that thing a pointer to be easy and we can also make that one a pointer if we really wanted to, doesn't really matter at this point, well it should matter because we're gonna be doing some stuff with it. We don't have any methods hanging off of it, but we could imagine we could actually move the get value, the set value.
[00:07:10]
We could actually move some of it to the data if we wanted it there, or we can move the save to the data and, so. We could do all that, we'll just keep everything as a pointer, we're not gonna attach any methods to it but if you wanted to get a little bit clever with it, mutated from there you could do that.
[00:07:26]
All right. If you think about set value remove value can really be internal to the data. All right. So there we go, we have the default projector. Which means we can actually just go right over here and go defaultProjector and just parse in the config. Awesome. So anytime we encounter an error we'll just do the defaultProjector which means down here at the bottom we'll also do it.
[00:07:47]
Now that we have the contents we now create the data object. So JSON is not as easy to handle in Go as it is in Rust or TypeScript, but it's still pretty easy. So we're gonna do this thing, we're gonna go var data Data. So what I'm saying here is, hey, I wanna create a variable called data with the type Data.
[00:08:08]
And then I'm gonna use err = json, of course this is one of the libraries that's provided. And I'm gonna do, I believe it's Unmarshal. Yeah, Unmarshal takes in a byte array and an object that I can write into. And so that's why we did this whole declaring a variable, and then we're gonna parse it in.
[00:08:28]
So we'll do Unmarshal, we parse in the contents of the file. And we're gonna pass in a reference to data, really it's a pointer to data at this point. And so it's gonna be able to write into that object everything, it's gonna Unmarshal the JSON for you. So if there is an error, well, we probably need to again return the defaultProjector.
[00:08:48]
If there's none, we can just return the actual projector itself with all the juicy, delicious contents. So let's just do it like that, right? And go data is, of course gonna be the data. And config, of course, is going to be config. Awesome. There we go. We've just done it.
[00:09:13]
We've created our beautiful projector. How nice is this? So there we go. Now I think we have pretty much everything done for our Go version. Now let's actually just do a little fun little count right here. All right. So our get value, get all value and set value and remove value starts at line 18 and ends at line 83.
[00:09:41]
So what is that? That's 65, right? Did I do my math correct, 65. Let's go back to our TypeScript one. Start here, it goes at 23 and ends at 79. So as you can see, TypeScript a little bit less, little bit kind of higher level, you can do things a little bit faster.
[00:10:01]
Go still it's not actually all that much more, right? A few extra lines of code are a bit more explicit, is that a win or lose? Up to you. Last time I did this I believe my Go and TypeScript won't actually have the same amount of lines. So I'm curious how did I add some extra lines in this?
[00:10:15]
Who knows, right, this is just the beauty of writing code line
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops