From d4109957788bc37a50b588738d51eeca17b1f5b1 Mon Sep 17 00:00:00 2001 From: Lewis Dale Date: Tue, 14 May 2024 13:03:13 +0100 Subject: [PATCH] Learning go: day 13 --- src/blog/posts/2024/5/learning-go-day-13.md | 85 +++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/blog/posts/2024/5/learning-go-day-13.md diff --git a/src/blog/posts/2024/5/learning-go-day-13.md b/src/blog/posts/2024/5/learning-go-day-13.md new file mode 100644 index 0000000..5a3af25 --- /dev/null +++ b/src/blog/posts/2024/5/learning-go-day-13.md @@ -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 + + + + + + Oopsie + + +

Oopsie uptime monitoring

+ + +``` + +```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. \ No newline at end of file