# Writing Chuck – Joke As A Service

Recently I really got interested to learn Go, and to be honest I found it to be a beautiful language. I personally feel that it has that performance boost factor from a static language background and easy prototype and get things done philosophy from dynamic language background.

The real inspiration to learn Go was these amazing number of tools written and the ease with which these tools perform although they seem to be quite heavy. One of the good examples is Docker. So I thought I would write some utility for fun, I have been using [fortune](https://en.wikipedia.org/wiki/Fortune_(Unix)), this is a Linux utility which gives random quotes from a database. I thought let me write something similar but let me do something with jokes, keeping this mind I was actually searching for what can I do and I landed up on jokes about Chuck Norris or as we say it facts about him. I landed up on [chucknorris.io](https://api.chucknorris.io/) they have an API which can return different jokes about Chuck, and there it was my opportunity to put something up and I chose Go for it.

JSON PARSING
------------

The initial version of the utility which I put together was way simple, it use to make a GET request stream the data in put in the given format and display the joke. But even with this implementation I learnt a lot of things, the most prominent one was how a variable is exported in Go i.e how can it be made available across scope and how to parse a JSON from a received response to store the beneficial information in a variable.

.gist table { margin-bottom: 0; }

// Chucknorris is the struct used to unmarshal the JSON response from the URL

type Chucknorris struct {

Category \[\]string \`json:"category"\`

IconURL string \`json:"icon\_url"\`

ID string \`json:"id"\`

URL string \`json:"url"\`

Value string \`json:"value"\`

}

/\* getJokes takes the API url as the parameter and fetch jokes from it,

\* here we have assumed it to be of ChuckNorris type

\*/

//TODO: Remove the dependency on the hardcoded struct

func getJokes(URL string) (string, error) {

req, err := http.NewRequest("GET", URL, nil)

if err != nil {

return "", fmt.Errorf("No request formed %v", err)

}

client := &http.Client{}

resp, err := client.Do(req)

if err != nil {

return "", fmt.Errorf("No response: %v", err)

}

defer resp.Body.Close()

respData, err := ioutil.ReadAll(resp.Body)

if err != nil {

return "", fmt.Errorf("Read error")

}

var joke Chucknorris

if err \= json.Unmarshal(respData, &joke); err != nil {

return "", fmt.Errorf("Error in unmarsheling, %v", err)

}

return joke.Value, nil

}

[view raw](https://gist.github.com/farhaanbukhsh/c428cd6a66e05d964c34ee1cea88ce61/raw/4b02d5d8a65dcf4234f534dfac48728244aba89b/initial.go) [initial.go](https://gist.github.com/farhaanbukhsh/c428cd6a66e05d964c34ee1cea88ce61#file-initial-go) hosted with ❤ by [GitHub](https://github.com)

Now the mistake I was doing with the above code is I was declaring the fields of the struct with a small letters this caused a problem because although the value get stored in the `struct` I can’t use them outside the function I have declared it in. I actually took a while to figure it out and it was really nice to actually learn about this. I actually learnt about how to make a `GET` request and `parse` the JSON and use the given values.

Let’s walk through the code, the initial part is a `struct` and I have few fields inside it, the `Category` field is a `slice` of string, which can have as many elements as it receives the interesting part is the way you can specify the `key` from the received JSON how the value of received JSON is stored in the variable or the field of the `struct`. You can see the `json:"categories"` that is the way to do it.

With the rest of the code if you see I am making a `GET` request to the given `URL` and if the it returns a response it will be `res` and if it returns an error it will be handled by `err`. The key part here is how `marshaling` and `unmarshaling` of JSON takes place.

This is basically folding and un-folding JSON once that is done and the values are stored to retrieve the value we just use a `dot` notation and done. There is one more interesting part if you see we passed `&joke` which if you have a `C` background you will realize is passing the memory address, pass by reference, is what you are looking at.

This was working good and I was quite happy with it but there were two problems I faced:

1.  The response use to take a while to return the jokes
2.  It doesn’t work without internet

So I showed it to [Sayan](https://twitter.com/yudocaa) and he suggested why not to build a joke caching mechanism this would solve both the problems since jokes will be stored internally on the file system it will take less time to fetch and there is no dependency on the internet except the time you are caching jokes.

So I designed the utility in a way that you can cache as may number of jokes as you want you just have to run `chuck --index=10` this will cache 10 jokes for you and will store it in a Database. Then from those jokes a random joke is selected and is shown to you.

I learnt to use `flag` in go and also how to integrate a `sqlite3` database in the utility, the best learning was handling files, so my logic was anytime you are caching you should have a fresh set of jokes so when you cache I completely delete the database and create a new one for the user. To do this I need to check of the Database is already existing and if it is then remove it. I landed up looking for the answer on how to do that in Go, there are a bunch of inbuilt APIs which help you to do that but they were misleading for me. There is `os.Stat`, `os.IsExist` and `os.IsNotExist`. What I understood is `os.Stat` will give me the status of the file, while the other two can tell me if the file exists or it doesn’t, to my surprise things don’t work like that. The `IsExist` and `IsNotExist` are two different error wrapper and guess what `not` of `IsExist` is not `IsNotExist`, good luck wrapping your head around it. I eventually ended up answering this on [stackoverflow](https://stackoverflow.com/questions/12518876/how-to-check-if-a-file-exists-in-go/49892959#49892959).

After a few iteration of using it on my own and fixing few bugs the utility is ready except the fact that it is missing test cases which I will soon integrate, but this has helped me learn Go a lot and I have something fun to suggest to people. Well, I am open to contribution and hope you will enjoy this utility as much as I do.

Here is a link to [chuck](https://github.com/farhaanbukhsh/chuck)!

Give it a try and till then Happy Hacking and [Write in GO!](https://youtu.be/LJvEIjRBSDA) 

Featured Image: https://gopherize.me/
