-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3cc17e0
commit cad2c1c
Showing
2 changed files
with
103 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--- | ||
title: "Joke API" | ||
weight: 9151 | ||
--- | ||
|
||
Try and solve the following. Every task has links to relevant documentation. | ||
|
||
### Request an API | ||
1. Begin with the following [main.go](main.txt) which requests a joke from https://official-joke-api.appspot.com/random_joke and decodes it into a Go struct. | ||
2. Refactor the HTTP request into another [function](/docs/basics/functions/) that returns `joke, error` | ||
3. Update the code to also [decode](/docs/standard-library/json/) and print the punchline | ||
4. [Delay](https://pkg.go.dev/time#Sleep) the punchline by a few seconds | ||
5. Make the delay configurable with a `--delay 10` [flag](https://pkg.go.dev/flag) | ||
|
||
### Build an API | ||
6. Write another program that [reads](https://pkg.go.dev/os#ReadFile) a [json file](https://github.com/15Dkatz/official_joke_api/blob/master/jokes/index.json) and picks a [random](https://pkg.go.dev/math/rand#Intn) joke | ||
7. Implement a [HTTP Server](/docs/standard-library/http-server/) that serves the picked joke | ||
8. Add a new endpoint that expects a joke and [persists](/docs/standard-library/io/) it | ||
|
||
### Use an API | ||
9. Write another program that asks the user to enter a joke on the command line (standard input) and [sends](/docs/standard-library/http-client/) it to your own API. | ||
|
||
|
||
## Tips | ||
|
||
{{%details title="Project structure"%}} | ||
You cannot have multiple `main` functions in a single directory. If you want to create multiple binaries, these must be separated into different directories. By convention the directory equals the binary name and is located under `cmd/` (e.g. `cmd/request-joke/main.go`). | ||
{{%/details%}} | ||
|
||
{{%details title="Prompt for input on the command line (standard input)"%}} | ||
With the [bufio](https://pkg.go.dev/bufio) package we can read from the standard input ([os.Stdin](https://pkg.go.dev/os#Stdin)) until a certain character occurs: | ||
|
||
```golang | ||
line, err := bufio.NewReader(os.Stdin).ReadString('\n') | ||
``` | ||
|
||
The [strings](https://pkg.go.dev/strings) package contains various functions to work with strings. For example [strings.TrimSpace](https://pkg.go.dev/strings#TrimSpace) to remove whithspace characters (spaces, newlines, etc.) from strings. | ||
|
||
```golang | ||
line = strings.TrimSpace(line) | ||
``` | ||
{{%/details%}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// If you want to create an executable binary, | ||
// you must name your package `main`. | ||
// By using another name, you create a library. | ||
package main | ||
|
||
// Import external modules that you would like to use | ||
import ( | ||
"encoding/json" // JSON encoding and decoding | ||
"fmt" // Formatting | ||
"io" // Input/Output | ||
"net/http" // HTTP requests | ||
"os" // Operating System | ||
) | ||
|
||
type joke struct { | ||
Type string | ||
// The json key can be overridden | ||
Message string `json:"setup"` | ||
} | ||
|
||
// The main function is called when executing the binary | ||
func main() { | ||
// Variables are declared using `:=` | ||
// The type is automatically evaluated and cannot be modified | ||
url := "https://official-joke-api.appspot.com/random_joke" | ||
// The following will not work: | ||
// url = 9 | ||
|
||
// Output a string to the terminal | ||
// %v detects the variable type. You may also use %s for strings and %d for digits | ||
fmt.Printf("Requesting joke from %v\n", url) | ||
// The following would also work: | ||
// fmt.Println("Requesting joke from", url) | ||
|
||
// Functions can return multiple results! | ||
// The variable names can be freely modified, | ||
// but using `err` for the error result is a convention. | ||
res, err := http.Get(url) | ||
// If the error is not nil, it means an error has occurred | ||
if err != nil { | ||
fmt.Printf("Error making http request: %v\n", err) | ||
// Exit the program with statuscode 1 | ||
os.Exit(1) | ||
} | ||
body, err := io.ReadAll(res.Body) | ||
if err != nil { | ||
fmt.Printf("Error reading response body: %v\n", err) | ||
os.Exit(1) | ||
} | ||
fmt.Printf("Body: %s\n", body) | ||
|
||
// Initialize a new instance of the joke struct | ||
j := joke{} | ||
// Pass a pointer of j to json.Unmarshal | ||
err = json.Unmarshal(body, &j) | ||
if err != nil { | ||
fmt.Printf("Error decoding body: %v\n", err) | ||
os.Exit(1) | ||
} | ||
fmt.Printf("%+v", j) | ||
} |