From 6e5af42d93d3d8a613987c39b5843407db53574e Mon Sep 17 00:00:00 2001 From: David Ashby Date: Sun, 21 Apr 2024 22:07:01 -0400 Subject: [PATCH] basic statement of intent --- .gitignore | 1 + cmd/furthur/main.go | 3 ++ go.mod | 3 ++ readme.md | 108 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 .gitignore create mode 100644 cmd/furthur/main.go create mode 100644 go.mod create mode 100644 readme.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8bbeb9d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/furthur diff --git a/cmd/furthur/main.go b/cmd/furthur/main.go new file mode 100644 index 0000000..38dd16d --- /dev/null +++ b/cmd/furthur/main.go @@ -0,0 +1,3 @@ +package main + +func main() {} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f4956b7 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.yetaga.in/alazyreader/going-further + +go 1.22.2 diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..01089ce --- /dev/null +++ b/readme.md @@ -0,0 +1,108 @@ +# Going Further + +This project aims to showcase "intermediate" go programming -- +once you've learned the language itself, what are the idioms that +make for a proficient go programmer? + +This is an implementation of a [golinks](https://golinks.github.io/golinks/) +service using only the standard library. + +## Structure + +The go toolchain is very unopinionated about how a project is laid +out, except for a few specific folder names and rules: + +* packages with `internal/` in the path can only be imported by other + packages that they share a "root" with. In go, any package that can + be loaded by the compiler can be pulled into another project, even + packages that weren't designed to be "libraries" in a traditional + sense. The `internal` convention was introduced as a way to allow + the authors of public (or even closed-source) code to truly keep + a package internal to its parent module. +* folders named `testdata` are ignored by the toolchain, and are used + to store exactly that -- files and data that tests are to use as + either input or validation. + +Outside of that, there are a few conventions that have become _relatively_ +common: + +* For modules that generate a command-line binary -- that is, those that + have a `main` package -- it's common to place that entrypoint file in a + subfolder of `cmd` named the same as the expected binary's name. In this + repo, that's `/cmd/furthur`. Running `go build ./cmd/furthur` in this module + results in a binary named `furthur`. +* Packages should be named after what they provide, and packages that collect + together a lot of related functionality aren't a negative thing. Package + names like `util` or `etc` are signs that your code is poorly laid-out. + If you find yourself needing to put a bunch of shared functionality into + one utility class, it might be a sign that all of the packages that use + that utility might actually be more coherent as one larger package. + * See the experience of the stdlib itself with [`io/ioutil`](https://pkg.go.dev/io/ioutil), + which ended up being entirely deprecated and moved into `io` and `os`. +* One pattern that used to be recommended before the advent of `internal` was + to explicitly place packages that were "intended" to be public in a folder + called `pkg`, but the community was never uniform in that approach, and + it is now generally discouraged. + +## HTTP Services + +## Generics + +Go has generics now, and they're useful... but mostly for authors of _libraries_, +not for application developers. They have allowed for the standard library +to finally ship a bunch of generic functions in the [`slices`](https://pkg.go.dev/slices) +package that developers used to have to write themselves. + +## //go:embed + + + +## Testing and Benchmarking + +## Concurrency + +It turns out channels are hard to reason about, but that's because _concurrency_ is +hard to reason about. + +Always remember that read/write access to a shared map _must_ be gated with a mutex. + +## Go Generate + +## Build tags + +## Logging + +`slog` package + +## init functions and globals + +Don't use them! They're hard to reason about and until recent versions of go +the order they ran in was undefined, leading to subtle bugs. + +## Common tools + +* `go vet` +* [`staticcheck`](https://staticcheck.dev/) + +## Other common idioms and stumbling blocks + +`./...` is a common shorthand to pass to parts of the go toolchain that means +"this directory and all directories underneath it". You'll often come across +it when running tests (`go test ./...`) or linters (`staticcheck ./...`). + +When working with closed-source code that is not cached in the public +[`GOPROXY`](https://proxy.golang.org/), you need to set `GOPRIVATE` to match +the name of the module or else you'll get cryptic errors when go tries to build. +This can be set globally for the entire toolchain using `go env`: +`go env -w GOPRIVATE="https://git.yetaga.in/*"`. See + +for more details. + +## Related Resources + +* Rob Pike's [Go Proverbs](https://go-proverbs.github.io/). Of particular value: + * _The bigger the interface, the weaker the abstraction._ + * _A little copying is better than a little dependency._ + * _Clear is better than clever._ + * _Don't just check errors, handle them gracefully._ +* Mat Ryer's [How I write HTTP services in Go after 13 years](https://grafana.com/blog/2024/02/09/how-i-write-http-services-in-go-after-13-years/)