Finish tomorrow's WeblogPoMo post
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m4s

This commit is contained in:
Lewis Dale 2024-05-12 21:48:27 +01:00
parent 351931dd4b
commit 406383e3c1

View File

@ -96,5 +96,65 @@ And if I then force a failure, it should also work:
## Adding some output ## Adding some output
Okay, now I have a database with some data in it, I'd like to expose that data Right, now to actually output the values in the database. First of all, I've defined the Struct for the response:
```go
// ping/ping.go
type PingResponse struct {
Site sites.Site
Timestamp string
Status string
}
```
And now I've added a `List` function that reads the data I need from the database, and places it into an array slice of `PingResponse` values:
```go
func List(db *sql.DB) []PingResponse {
rows, err := db.Query(`SELECT sites.url as url, sites.name, ping.timestamp as timestamp, statuses.name as status FROM ping
JOIN sites ON ping.site = sites.url
JOIN statuses ON ping.status = statuses.id
ORDER BY timestamp DESC`)
if err != nil {
panic(err)
}
defer rows.Close()
pings := make([]PingResponse, 0)
for rows.Next() {
p := PingResponse{}
rows.Scan(&p.Site.Url, &p.Site.Name, &p.Timestamp, &p.Status)
pings = append(pings, p)
}
return pings
}
```
The interesting parts here are the `defer` statement, and `rows.Scan`. Defer queues that call up until after the function has executed, it's just a way of saying "I will be doing this at the end regardless" as a cleanup operation[^2]. Then `rows.Scan` will automagically insert the values to the variables I pass it, in the order the columns are read from the database[^3].
Then finally, I can update my handler function so that it uses `json.Marshal` to convert the pings to JSON, and output them to the browser:
```go
http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
pings := ping.List(db)
if output, err := json.Marshal(pings); err != nil {
w.Write([]byte(err.Error()))
w.WriteHeader(http.StatusInternalServerError)
return
} else {
w.Header().Set("Content-Type", "application/json")
w.Write(output)
}
})
```
And that works! You can see it at https://oopsie.lewisdale.dev, with (hopefully) some actual output.
[^1]: Yes, despite what I said in another post I've not written any _actual_ tests. I'm human, alright? [^1]: Yes, despite what I said in another post I've not written any _actual_ tests. I'm human, alright?
[^2]: I think
[^3]: This is where it helps to be explicit with what is selected and avoid `SELECT *`.