Day 7: Project setup
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m9s
All checks were successful
Build and copy to prod / build-and-copy (push) Successful in 2m9s
This commit is contained in:
parent
035710ef47
commit
1b1c3e6636
90
src/blog/posts/2024/5/learning-go-day-7.md
Normal file
90
src/blog/posts/2024/5/learning-go-day-7.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
---
|
||||||
|
title: "Learning Go: Day Seven"
|
||||||
|
date: 2024-05-07T08:00:00.0Z
|
||||||
|
tags:
|
||||||
|
- learning
|
||||||
|
- go
|
||||||
|
excerpt: "Kicking off the project by starting to build out an HTTP server"
|
||||||
|
---
|
||||||
|
|
||||||
|
So, yesterday I [decided I was going to build an uptime monitor and status page](/post/learning-go-day-six.md). To recap, here's the list of things I need to figure out how to do:
|
||||||
|
|
||||||
|
* Run a web server
|
||||||
|
* Render web pages with some dynamic content
|
||||||
|
* Store & read data from/to a database
|
||||||
|
* Send requets to a server & handle the responses
|
||||||
|
* Do all of the above on a periodic schedule
|
||||||
|
|
||||||
|
I've decided to call the project Oopsie, because that's what I'll say when things go red, and have setup the repo on [my git server](https://git.lewisdale.dev/lewis/oopsie). Like on [day one](https://lewisdale.dev/post/learning-go-day-one), I initialised my Go module:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod init lewisdale.dev/oopsie
|
||||||
|
```
|
||||||
|
|
||||||
|
And then created my `main.go` file.
|
||||||
|
|
||||||
|
## Creating a web server and handling my first request
|
||||||
|
|
||||||
|
Once again, Go's standard library comes to the rescue, as there are libraries for dealing with HTTP requests built right into the runtime. The [net/http package](https://pkg.go.dev/net/http) has functions for creating a server, listening for requests, and even serving static assets, which is really useful.
|
||||||
|
|
||||||
|
My first server, and request handler, is the ever-original "Hello, world":
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Hello, World!"))
|
||||||
|
})
|
||||||
|
http.ListenAndServe(":8000", nil)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It's fairly straightforward. The `http.HandleFunc` call registers a handler on the root URL, and `http.ResponseWriter.Write` outputs a string, which is converted to a slice of bytes. Then I start the actual server on port 8000 with `http.ListenAndServe`. Truly, riveting stuff.
|
||||||
|
|
||||||
|
|
||||||
|
## Pattern-matching handlers
|
||||||
|
|
||||||
|
The pattern syntax for `HandleFunc` is something called ServeMux, which I don't fully understand but fortunately the syntax is well-documented on the [package docs](https://pkg.go.dev/net/http#hdr-Patterns). It's not too dissimilar to most other URL pattern-matching libraries[^1]. Generally the syntax is:
|
||||||
|
|
||||||
|
1. `/` - match the root
|
||||||
|
2. `/something` - explictly match a URL
|
||||||
|
3. `/something-else/` - matching any URL where the path starts with `/something-else/`
|
||||||
|
4. `/route/{param}` - match a URL that starts with `/route/` and then has an arbitrary parameter in the second block of the path
|
||||||
|
|
||||||
|
You can also prefix the paths with either the request method, host name, or both. For example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("This was a GET request!"))
|
||||||
|
})
|
||||||
|
http.HandleFunc("POST /", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("This was a POST request!"))
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
So then if I perform a POST request:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8000
|
||||||
|
> This was a POST request!%
|
||||||
|
```
|
||||||
|
|
||||||
|
And then just a GET request:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8000
|
||||||
|
This was a GET request!%
|
||||||
|
```
|
||||||
|
|
||||||
|
That's a pretty powerful pattern-matcher to have straight out of the box. The only thing I'm less keen on is the `w.Write` syntax, but that's extremely minor. It'll be interesting to see how I get on.
|
||||||
|
|
||||||
|
[^1]: I still prefer Express-style pattern matching because inertia
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user