Learning go: day 13
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m12s

This commit is contained in:
Lewis Dale 2024-05-14 13:03:13 +01:00
parent 8f30bed874
commit d410995778

View File

@ -0,0 +1,85 @@
---
title: "Learning Go: Day Thirteen"
date: 2024-05-15T08:00:00.0Z
tags:
- learning
- go
excerpt: "Creating some basic HTML output, and bundling static files"
---
So now I want to start working on putting together a basic interface. This post won't be about creating the interface itself, but instead just the ground work that will allow me to build it over the next post or two.
## Creating some HTML output
Alright, this was actually really straightforward. There's a module called [html/template](https://pkg.go.dev/html/template) that can be used to parse HTML, and includes a templating language.
So I've created a super-simple HTML template at `templates/index.html`, and then use the `template.ParseFiles` function to parse and display it:
```html
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Oopsie</title>
</head>
<body>
<h1>Oopsie uptime monitoring</h1>
</body>
</html>
```
```go
// main.go
http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
pings := ping.ListGroupedBySite(db)
if _, err := json.Marshal(pings); err != nil {
w.Write([]byte(err.Error()))
w.WriteHeader(http.StatusInternalServerError)
return
} else {
w.Header().Set("Content-Type", "text/html")
t, _ := template.ParseFiles("templates/index.html")
t.Execute(w, nil)
}
})
```
This works! But I can't deploy it, because when I compile the binary and upload it to my server it can't find the template files. Luckily, there's a package that can help me do that.
## Bundling static files
This part is basically magic. I have no idea how it works, but there is a package called [embed](https://pkg.go.dev/embed). I can use it to create an instance of `FS` with some bundled static content, and that then gets bundled into my binary, and it takes about 3 lines of code to do it 🤯.
```go
// main.go
import (
"embed"
)
//go:embed templates/*
var content embed.FS
http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
pings := ping.ListGroupedBySite(db)
if _, err := json.Marshal(pings); err != nil {
w.Write([]byte(err.Error()))
w.WriteHeader(http.StatusInternalServerError)
return
} else {
w.Header().Set("Content-Type", "text/html")
t, _ := template.ParseFS(content, "templates/index.html")
t.Execute(w, nil)
}
})
```
And then when I run `go build`, the resulting binary file has the HTML bundled in it and I can run it on my server. This is a _really_ powerful thing to have built directly into the standard library.
So that's it for today, like I mentioned earlier, my next one or two posts will mostly be focused on making a UI.