Welcome to Div Rhino, a channel dedicated to project-based learning. If you find the videos here to be helpful, please like them and consider subscribing for more content. In this tutorial, we're going to learn how to build a dad joke CLI tool with Go and Cobra. To follow along, you will need to have Go and the Cobra Generator installed. You can find links to the installation pages in the description for this video. Before I begin, I'll change into the "Sites" folder, which is the directory where I keep my projects. Here we can create a new folder for our "dadjoke" project and then we can change into it. Inside our project directory, we can initialise a new project using the cobra init command provided to us by the Cobra generator. Usually, you will want to name your package based on a URL that belongs to you. Here our package name is using "example", but feel free to use your own github name instead. Remember this package name because we will be using it in different parts of our program. If we list the items of our directory, we will see that Cobra init created a License, a command folder and a main.go file. We will be using Go modules to handle our dependencies, so let's initialise that now. If you notice, we are using the same package name that we used to initialise our cobra app, earlier. When we list the folder items now, we will see that we now have a go.mod file. This means the command ran, successfully. Let's open our project up in a text editor. I am using VS Code, but you can use whichever text editor you're comfortable with. Cobra created a simple app for us, everything is wired up and working. We just need to build on to it. If we run our programme for the first time, we'll see that all our dependencies are being installed first. But towards the end, we can see the placeholder cobra description. Let's go ahead and change this placeholder text to something that better describes our app. There is a short description and a long one. We will update both. If we run our programme now, we'll see the Long description we just added. Cobra makes it easy for us to add our own commands. So let's do that now. We can use the cobra add command to create a new command of our own which we will call "random". Cobra created a brand new random.go file for us inside the cmd directory. Let's open it up and take a quick look at it. If we run our programme now, we will see that "random" is now being listed under the available commands. Let's quickly update the long and short description for our new random command We will be using the icanhazdadjoke API to provide us with jokes data. So let's take a look at their documentation first. This API doesn't require authentication, so we won't need to worry about that. However, it does ask that we include a
custom "user-agent" header to describe how we're using the API. This is fair, so we'll make sure to do that. A little further down, we can see the endpoint that we are interested in If we paste the example curl command into a terminal, it will return a joke as a JSON response. We can see that a joke has an ID, some joke text and a status code. We can represent this joke structure as a struct within our Go code. Let's first clean up these comments so it's easier for us to see what we're working with. Let's create a Joke struct type This joke struct will have an ID that will be of type string A joke, that will also be of type string And a status, that will be of type int We will need a method that we want to call every time we run our random command. Let's create this new method and name it get random joke For now, let's just make it print out a little message In order for us to see it in action, we need to tell the RUN command to call it. If we run our random command now, we will see the little message from our getRandomJoke method. Next, we want a way to make a request to the API endpoint. We can achieve this by using the http package from the Go standard library. In the http package docs, let's search for func Get. There is a line that says we should use New Request along with DefaultClient.Do if we'd like to make a request with custom headers. This is the approach we will take because we do, in fact, want to make a request with custom headers Back in our random.go file, let's import the http package And then let's also create a new method that connects to the api and requests a random joke. We will call this new method "getJokeData" getJokeData will take in the baseAPI url as it's only argument. This argument will be of type string. The getJokeData method will return a slice of byte Inside the body of the getJokeData method, we will use the NewRequest method from the http package to create a new request. The NewRequest takes in 3 arguments. First it takes an http method, then a url and then a request body The new request method returns 2 values. It returns a request and an error. Let's do some quick error handling before we move on. Now we can add a couple of custom headers. First we add a header to let the API know we'd like our data encoded as JSON Then we will add the custom User Agent header and briefly describe how we will use the API Now that we have our response ready, let's pass it in to the defaultClient.Do method. The defaultClient.Do method returns 2 values. It returns a response and it returns an error Let's do some quick error handling before we move on We will need to import the ioutil package so that we can have access to the ReadAll method We will use the ReadAll method
to read our response body The ReadAll method returns 2 values. It returns the response in bytes and it also returns an error. Let's do some quick error
handling before we move on Our getJokeData method is almost done. We just have to return the responseBytes We can now start using our getJokeData method inside our getRandomJoke method. We don't need the little message anymore, so we can remove it. Oh, but before we go any further, we should probably import the JSON package because we need if for the Unmarshal method. The unmarshal method takes 2 arguments. The first argument is data of the type slice of byte and the second argument is an interface into which it can save the parsed results It has only one return value, which is an error Let's first set up the data that we can pass as the first argument to the Unmarshal method. Remember that our getJokeData method returns a slice of byte. That is the type that we need for our first argument. The getJokeData needs a URL, so let's give it the icanhazdadjoke api URL Let's pass our first argument
to the Unmarshal method and set up our second argument. Our second argument is an interface into which we can store parsed values. Let's set up a joke variable which will be a Joke struct We'll pass a pointer to joke as our second argument The unmarshal method returns an error, so let's do some quick error handling before we move on. Because the error is the only return value, we can use this syntax to declare and return it all at once. The last remaining step for our getRandomJoke method is for us to actually print out our random dad joke. We only want the joke text, though. and we can access this from the joke variable using dot notation. So joke.Joke is what we're looking for. We should probably think of better key names for next time, though. We'll also want to convert this to a string Now we can use our newly-created CLI tool to get a random dad joke. Let's use the random command to do that a few times. Just to see that it's actually random And there you have it. In this tutorial, we learnt how we could build a command line tool with Go and Cobra. A text version of the tutorial can be found on divrhino.com and a repo can be found on my github account. I'll leave both links in the description for this video. If you found this video useful, please like it and consider subscribing to my channel. Thank you for watching. <3