Actually following lets-go book

drew/lets-go
Drew Bednar 6 days ago
parent 103e1d5b4e
commit 0bc80e3cd7

@ -0,0 +1,52 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main cmd/ratchetd/main.go"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "go.tmpl"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
silent = false
time = false
[misc]
clean_on_exit = false
[proxy]
app_port = 0
enabled = false
proxy_port = 0
[screen]
clear_on_rebuild = false
keep_scroll = true

1
.gitignore vendored

@ -21,3 +21,4 @@
# Go workspace file
go.work
tmp/

@ -3,6 +3,8 @@
An example web application in Golang.
https://lets-go.alexedwards.net/sample/02.09-serving-static-files.html
## Project Structure
Loosely inspired by the organization of [WTFDial](https://github.com/benbjohnson/wtf?tab=readme-ov-file#project-structure),

@ -1,11 +1,12 @@
package main
import (
"fmt"
"os"
"log"
"net/http"
"strings"
"git.runcible.io/learning/ratchet"
ratchethttp "git.runcible.io/learning/ratchet/internal"
)
var (
@ -17,5 +18,8 @@ func main() {
// Propagate build information to root package to share globally
ratchet.Version = strings.TrimPrefix(version, "")
ratchet.Commit = commit
fmt.Fprintf(os.Stdout, "Version: %s\nCommit: %s\n", ratchet.Version, ratchet.Commit)
server := ratchethttp.NewRatchetServer()
log.Print("Listening on http://localhost:5001/")
log.Fatal(http.ListenAndServe(":5001", server))
}

@ -0,0 +1,97 @@
package ratchet
import (
"fmt"
"html/template"
"log"
"net/http"
"strconv"
)
type RatchetServer struct {
http.Handler
//Services used by HTTP routes
UserService UserService
}
func NewRatchetServer() *RatchetServer {
r := new(RatchetServer)
router := http.NewServeMux()
// /{$} is used to prevent subtree path patterns from acting like a wildcard
// resulting in this route requiring an exact match on "/" only
// You can only include one HTTP method in a route pattern if you choose
// GET will match GET & HEAD http request methods
router.HandleFunc("GET /{$}", home)
router.HandleFunc("GET /snippet/view/{id}", snippetView)
router.HandleFunc("GET /snippet/create", snippetCreate)
router.HandleFunc("POST /snippet/create", snippetCreatePost)
r.Handler = router
return r
}
func home(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Server", "Go")
// Initialize a slice containing the paths to the two files. It's important
// to note that the file containing our base template must be the *first*
// file in the slice.
files := []string{
"./ui/html/base.go.tmpl",
"./ui/html/partials/nav.go.tmpl",
"./ui/html/pages/home.go.tmpl",
}
// read template file into template set.
ts, err := template.ParseFiles(files...)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// Write template content to response body
err = ts.ExecuteTemplate(w, "base", nil)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
func snippetView(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(r.PathValue("id"))
if err != nil || id < 1 {
http.NotFound(w, r)
return
}
// Set a new cache-control header. If an existing "Cache-Control" header exists
// it will be overwritten.
w.Header().Set("Cache-Control", "public, max-age=31536000")
// msg := fmt.Sprintf("Snippet %d...", id)
// w.Write([]byte(msg))
// we can rely on the Write() interface to use a differnent
// function to write out our response
fmt.Fprintf(w, "Snippet %d...", id)
}
// snippetCreate handles display of the form used to create snippets
func snippetCreate(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Displaying snippetCreate form..."))
}
// snippetCreate handles display of the form used to create snippets
func snippetCreatePost(w http.ResponseWriter, r *http.Request) {
// example of a custom header. Must be done before calling WriteHeader
// or they will fail to take effect.
w.Header().Add("Server", "Dirp")
w.WriteHeader(http.StatusCreated)
w.Write([]byte("Created snippet..."))
}

@ -0,0 +1,19 @@
{{define "base" -}}
<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>{{template "title" .}}</title>
</head>
<body>
<header>
<h1><a href='/'>Ratchet</a></h1>
</header>
{{template "nav" .}}
<main>
{{template "main" .}}
</main>
<footer>Powered by <a href='https://golang.org/'>Go</a></footer>
</body>
</html>
{{end}}

@ -0,0 +1,6 @@
{{define "title"}}Home{{end}}
{{define "main" -}}
<h2>Latest Snippets</h2>
<p>There's nothing to see yet!</p>
{{- end -}}

@ -0,0 +1,5 @@
{{define "nav" -}}
<nav>
<a href='/'>Home</a>
</nav>
{{- end}}
Loading…
Cancel
Save