Check out a free preview of the full Polyglot Programming: TypeScript, Go, & Rust course:
The "Process CLI Args 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 the setup for the Go version of the CLI project by implementing a simple CLI parser to parse out the args, config, and pwd.

Get Unlimited Access Now

Transcript from the "Process CLI Args Go" Lesson

[00:00:00]
>> Awesome, so we've kind of finished the old TypeScript side of things, right? We've already flown right through it. How do you feel about this? You guys liked this? Pretty good, right? Nothing too bad here. The Go version is, I'd say. Less and More boilerplate at the exact same time, so let's look at that one.

[00:00:18] Let's do the do the exact same thing. Now I'll just navigate to your Go project. I'm just gonna reuse the same one so I don't have to do the whole go mod net here are some long URL. I'm just going to reuse this one it has everything I need in it anyways and so let's delete this, yeah let's delete.

[00:00:33] That in fact I can I mean I guess I could have kept these I'll just keep p2 and we'll call this one projector there we go Op. Projector, awesome. And then let's create main.go. So now we have this nice main.go, you can see right here. So I have my go project inside my command because remember that's where all of your binaries should be inside a sub folder projector main.go.

[00:01:00] Of course you always in the main package you should specify you are the main package to identify the compiler exactly what to do and of course you should have the main function available right there, so there you go, it knows exactly where to go. So now, just like the project structure I showed you earlier, we're going to jump out of command and we're going to create a pkg, the package folder, and in there let's create a sub package.

[00:01:23] Now, we have a bunch of different options in which we could do this. We could do this, let's just call this sub package, let's just call it the config. I'm gonna do something probably different than my code is online, but it's good to mix things up. Try different stuff.

[00:01:35] So let's have a subdirectory called config. And in here, let's create an ops doc go. And of course you give it the package name of config, right here. So just to make sure we can kind of test these things out and you can understand how these communication works, let's create a just a simple struct.

[00:01:54] I'm just going to literally call struct, struct. And let's go back to our main doc go here. And what I can do is I can go like this, I can go config. And you'll notice that this one is actually the Go Delve package config. So that's not that good.

[00:02:09] And if I go down one, this is another config and so there looks to be some configs out there and it's not picking up my config which is a little upsetting, right? So I should have a config myself and I should be able to do struct. Why are you not doing that?

[00:02:27] Let's not call it config then. Maybe there's too many collisions here, we'll just call projector. Keep it nice and plus it's just little honestly it's a little bit nicer there we go we have this nice beautiful projector. We have a single struct being XR exported. And now we have our main file and we have our package file, right, so, we main file of course is where we do all our main execution packages where we put all of our library code.

[00:02:53] All right, awesome, so now long as everything's working nicely, which my LSP is still not working nicely, so I'm just gonna quit it out for a second, restart backup. Give it a moment to breathe the effervescence we talked about them earlier. All right, so now I should be able to get projector.

[00:03:11] There you go, now can find it just fine. You can see how it's even done, so remember the go mod a knit was this right here. Remember when I did this I called it AOC, okay, adventive of code. We have to call it ad vented code, could have been called projector, whatever your go mod a knit call all is, this is it right here, subpage package, subpage of that projector, all right.

[00:03:30] So now I've even given it a name, projector that was the top line, package projector and everything, and when I do this, you can see there's a single exported truck. Just like we told you, and if you go back here and you have some sort of function that is lowercase, right, you will not see this function of course, right?

[00:03:45] So when I do this lowercase just does not exist. Remember, you always have to capitalize. Don't forget that, all right? Pretty easy, pretty straightforward. So let's start right now and start doing this. So we do need that extra additional library. So, let's go grab that command from this page right here which is gonna be, we're gonna do go get this, right, let's see if I did I paste it in here.

[00:04:09] I talked about how I use Vim and Dvorak and how about awesome it is, but we're not gonna do that. So we're gonna do go get, right. All right, awesome. So don't forget to use this and go go get GitHub hell flame argparse. Awesome, it got it we're at one point 8.0, hopefully you guys get the same experience Give everyone a second everyone get it.

[00:04:37] We're good. Everyone follow along, awesome. All right, so I wanna do effectively the exact same thing. Let's create a struct that is the opts. And then let's we're gonna transform that into the config and a little bit. So let's create a type opts struct and it's gonna have effectively similar item on it.

[00:04:57] So we also want Args, now remember we have to capitalize it if you wish to export it. So this is one of the unfortunate parts but it is, right? And we're gonna call this thing a string array, right? So this thing is an array of strings and we're just gonna keep it this way.

[00:05:11] It's not gonna be nullable like the previous one. And so then we also need the config, which of course is gonna be a string. And we're also gonna have the present working directory, which is gonna be the string and go prefers it if they're all lined up like that.

[00:05:24] So there you go. We have this beautiful nice struct. It's almost one to one the exact same as the previous one. Let's go right here. As you can see, it's almost one to one. This one, obviously this library had novels. The other one, we're not gonna have novels.

[00:05:39] We'll just have empty strings. So similar feel. So now let's go like this, funk get ops, right? It's gonna return and ops, so likely there's only I always feel like there's almost always errors when dealing with stuff so I'm just gonna pre prepare for it, right. I'm just gonna assume we're gonna return a pointer to ops and an error, this is probably the safest way to go, honestly.

[00:06:04] So, the first thing we need to do is actually create a parser for the CLI ops. So I'm gonna go like this parser, a parser equals new. Now remember our thing was called argh parse. As you start typing it. You'll see right away. You can see it right here, argh, parse.

[00:06:21] Awesome, right? So I'm gonna press yes on this thing. Hopefully you have auto import and everything set up. And now we have a couple of different options here. The LSP by the way for girls, one of the best LSPs out there almost always give you the right things to do.

[00:06:33] And you'll see right here, right as I inevitably do parser when I open this up as I start, if I start doing things, it's gonna give me all the right stuff to do, right, for the most part. Now let's see. Did I create it right? Is it new per se?

[00:06:48] It's a new person. Am I bad on that one? So let's do this. And what is new parser? Take layer yell. So it takes in the name of your program, a description of your program, and a parser config, a pointer to a parser config and of course, what does it return to you a pointer of a parser, awesome.

[00:07:04] So, let's go back and let's just do that. What is the name of our program? Projector, what is the description gets all the values, right? It's just the greatest at these things. And so now we need that parser config. Of course the LSP is like I said, it's really good look at that.

[00:07:18] It even has given you everything you need. I'm gonna give you an ampersand to this thing. It does it all for you. Very, very wonderful. There is one option we need, you wouldn't know about this option unless if If you've played around with this library. But it's called it starts with a capital D and I know I will see it right away disabled default show help whenever you execute for whatever reason it shows the Help menu.

[00:07:38] And that kind of ruins this whole idea of if you ask for a value you don't wanna help menu, right you [LAUGH] Really hurts. Really just painful experience right there. All right, so we need to set up our items, now, remember how we can pass pointers around? Well, you can't technically pass pointers to strings or string arrays, and then the other side of the application can go and fill in those values and give you the correct stuff and then you'll just have them.

[00:08:05] So we're gonna do that now. With this, it kind of does it for you, but it will I'll show you what it means when we're actually inside of or when we're returning the ops object. So first, let's do arcs right because that's like the first one. So arcs have is gonna be the parser dot strings, right?

[00:08:21] They kind of already have it set up for you and it's saying right here, it takes in a short string, a full string and a arc parse options. And returns to a pointer to a string array, which means they're probably gonna do something to that string array for us.

[00:08:35] Or we're just gonna have access to it, so let's do that right now. So if it wasn't short first, yes, short first, so let's go like this. It doesn't really matter, but we'll go args full args, right, because this is gonna be the positional arguments. So there is no way to refer to them as a dash-dash or we don't want that.

[00:08:55] And so the last thing is gonna be this Option business. So we need to make sure we go through the option and get the correct things. Now, you would think that it's positional. I've actually tried it on positional, it doesn't seem to be positional. Let's just go back and let's just make it happen.

[00:09:09] All right, so I'm gonna add in positional just, you it should be the positional ones, right? I read through the documentation. I couldn't find all the answers for myself. Is it required, no it's not required, right. So let's just do that and go false we don't actually need this one 100% of the time.

[00:09:29] And anything else we need I think there's at least one more, I think there's a default value one is in multiple let's see default, there you go default argument value. Is that the one? Let's see. If not given now, it's definitely not that. We don't want that one.

[00:09:45] So I'm trying to remember what it was because is it Multi takes more than one argument, Hint, Groove, my goodness, I may have forgotten I think I just put it right here just in case I forget. Default is this okay? So it was this, okay? It was default.

[00:10:00] All right, there it is. Sorry I knew I forget using some of these libraries, all right. Default, there we go, awesome, so we have the Args, we've parsed them out, this is what it's gonna be and so now we need to just do the same thing for the other ones.

[00:10:15] So config is gonna be a parser ,and it's just gonna be a string, and we should name this one definitely correct, right. Config and do we need any options, yes, we don't want it to be required, right. We should not fail the application if they do not provide us a config because we should have a default location for a config Okay, so I'm gonna go like this required, no false and of course the default value, I'm just gonna have as an empty string, right, that's perfectly fine for me, I'm happy with it, yay.

[00:10:47] And let's do one more, present working directory, P for present working directory and of course present working directory. So that should be everything we need. And now we just simply need to let this program parse the command line for us, and so if we do parser.Parse, it will do that and guess what it returns.

[00:11:06] Well, everyone's favorite An error, right, you can see right here? It can take in a string array and it returns out an error so we don't need to pass anything in we'll do that and we'll do the classic handling of the air that's why you should have this on a hot key.

[00:11:21] So you can just make it happen right away. So if you're programming go, it's straightforward. And at that point, all we need to do now is just return the reference to an ops and a nail. And of course, what do we have in the ops, we have the args, which is gonna be args.

[00:11:36] But we need to do that we need to dereference that we're actually gonna copy out and get out those values and hand them back. And do the exact same thing with config, we're gonna do the exact same thing with present working directory. Awesome, there we go. We have everything we need.

[00:11:55] Everyone's feeling good about this one kind of a lot of work, right? Like I said, Gil just always feels like it has a lot of boilerplate. But, when everyone has to program the same way, there's also something kind of nice about that. I don't know if you've ever gotten deep into the JavaScript metaprogramming where you just have stuff doing stuff about and just gets super confusing.

[00:12:13] Go just doesn't allow you to do that. So its simplicity hurts it and is really awesome at the exact same time. So there we go, we should be able to take this function now. Did I add any semicolons? Let's see if I did, Nice. That is a victory right there.

[00:12:28] All right, so now we can go back to Maine and we can just call get Ops, right? And of course, we need the opts and the err, and we should handle this correctly. So, to me, it seems, like if there's an error, we should just print this out and terminate the program, right?

[00:12:43] So, this would actually be a very good case for using log right here, right? So I'm gonna use log and just fatal printed all out and we'll use fatal F and we'll just say, unable to get options and use V and then just pass in the error, right?

[00:13:00] To me, that is a pretty nice way of doing things. Now we're not gonna actually use the options other than printing them right now. So let's just print them out right now so we can just see what's happening. Do a little print f like this opts, and +V opts awesome.

[00:13:17] So let's jump back here and go run projector that and what you'll see is, we've effectively got an array with nothing in it, a config, and a present working director. So it's almost identical to our other program, this is just how they use it, awesome. So, we can definitely take this and convert it into what we need it to be.

[00:13:35] Let's do a quick testing test, you can see that awesome foo, great, config bar, awesome. It looks like it's just exactly kind of what we wanted it to be. And just for the completeness, let's do present working directory bass, awesome. So everything's passable, everything works