Building on Minimal three tier Golang app, I made a three tier app with a Go frontend (as Web Assembly), a Go backend and a .txt as exemplary “data store”. Still no external dependencies, all compiling to a single binary. You need Go, Make and a browser. Compile and start with make, then open http://localhost:8000 and hit the button.
$ cat Makefile
all: hellofront hello
hellofront: hellofront.go
GOOS=js GOARCH=wasm go build hellofront.go structures.go
hello:
go run hello.go structures.go
$ cat structures.go
package main
type Answer struct {
Current int
}
$ cat hellofront.go
package main
import (
"encoding/json"
"fmt"
"net/http"
"syscall/js"
)
var current js.Value
func main() {
done := make(chan struct{}, 0)
current = js.Global().Get("document").Call("getElementById", "current")
js.Global().Set("GetCurrent", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go GetCurrent()
return nil
}))
<-done
}
func GetCurrent() {
resp, err := http.Get("/current")
if err != nil {
fmt.Println(err)
}
var res Answer
err = json.NewDecoder(resp.Body).Decode(&res)
if err != nil {
fmt.Println(err)
}
current.Set("innerText", res.Current)
}
$ cat hello.go
package main
import (
_ "embed"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
//go:embed hellofront
var wasm []byte
// copied from $(go env GOROOT)/misc/wasm/wasm_exec.js
//go:embed wasm_exec.js
var wasm_exec string
var html = `<html>
<head>
<script>` + wasm_exec + `</script>
<script>
const go = new Go();
var module = WebAssembly.instantiateStreaming(fetch("hellofront"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body>
<h1 id="current"></h1>
<button onclick="GetCurrent()">Load Current</button>
</body>
</html>
`
const storefile = "myfancydatastore.txt"
func readFromStore() Answer {
b, err := ioutil.ReadFile(storefile)
if err != nil {
// do something
}
var a Answer
err = json.Unmarshal(b, &a)
if err != nil {
// do something
}
return a
}
func writeToStore(a Answer) {
b, err := json.Marshal(a)
if err != nil {
// do something
}
ioutil.WriteFile(storefile, b, 0644)
}
func serveIndex(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
w.Header().Set("content-type", "text/html; charset=utf-8")
w.Write([]byte(html))
}
}
func handler(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
w.Header().Set("content-type", "application/json")
a := readFromStore()
b, err := json.Marshal(a)
if err != nil {
// do something
}
w.Write(b)
a.Current = a.Current + 1
writeToStore(a)
}
}
func loadWASM(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
w.Write(wasm)
}
}
func main() {
writeToStore(Answer{Current: 0})
mux := http.NewServeMux()
mux.HandleFunc("/", serveIndex)
mux.HandleFunc("/current", handler)
mux.HandleFunc("/hellofront", loadWASM)
fmt.Println("Starting server on localhost:8000")
http.ListenAndServe("localhost:8000", mux)
}
I guess what I was thinking of in Receiver-side Cutoff is just IRC without bouncers. People can’t continue sending when you’re not connected. Seems like a good idea. Also no GDPR/DSGVO problems, because messages aren’t saved.
… Peter Welch wrote
After six or seven years in this professional clink, what people pay software engineers for is their knowledge of what not to do. If my friends and family ask me to build them a website I send them to Squarespace, since it will be much cheaper and probably better than anything I could do for them. We get paid to grasp the ecosystem at large, stay vaguely up to date, and divert ruinous architectural traps before they show up on a quarterly report. Anyone can google the solutions to most of the particular problems we deal with; we get paid to know what to google and how to read the answer.
[…]
The fact that grammatically or syntactically correct semi-nonsense collected from shallow knowledge can displace real world tests of comprehension means we’re not holding ourselves to a particularly high standard. Actual use of ChatGPT for articles or essays or code will produce more of the content that made its output subpar, and achieve little besides accelerating the homogenization of mediocrity.
Ouch!