diff --git a/docs/go/advanced/context.md b/docs/go/advanced/context.md new file mode 100644 index 0000000..de36021 --- /dev/null +++ b/docs/go/advanced/context.md @@ -0,0 +1,41 @@ +# Context + +Context is a way of passing information or enforcing timeouts when calling functions throughout your application as a single requests goes from layer to layer. This is usually passed as the first parameter in your functions if being used. + +```go +// create an empty context +ctx := context.Background() + +// append value to context +ctx = context.WithValue(ctx, "key", "value") + +value := ctx.Value("key") +``` + +## Timeouts + +```go +ctx, cancel := context.WithTimeout(context.Background(), 2 * time.Second) + +defer cancel() // can call before timeout +go longRunningFunc(ctx) + +select { +case <-ctx.Done(): + fms.Println("done blocking main thread also!") +} +time.Sleep(2*time.Second) + +func longRunningFunc(ctx context.Context) { + for { + select { + case <-ctx.Done(): + fmt.Println("timed out") + return + default: + fmt.Println("still processing") + } + time.Sleep(1*time.Second) + } +} +``` diff --git a/docs/go/advanced/flags.md b/docs/go/advanced/flags.md new file mode 100644 index 0000000..c18635b --- /dev/null +++ b/docs/go/advanced/flags.md @@ -0,0 +1,62 @@ +# Flags + +Flags allow you to define command line arguments to your applications. This gives you some more useful features over `os.Args` such as help strings and validation. + +```go +var age = flag.Int("age", 20, "age of user") // arg name, default, help +fmt.Println(*age) // gives us a pointer to the value +// or +var age int +flag.IntVar(&age, "age", 20, "age of user") +fmt.Println(age) + +// with structs +type ServerConfig struct { + port int + env string +} + +var config ServerConfig +flag.IntVar(&config.port, "port", 8000, "server port") +flag.StringVar(&config.env, "env", "dev", "environment") +flag.Parse() +``` + +## Custom Flags + +Normally flags can only be strings, ints, or booleans, but you can create your own custom flag types by implementing the `Value` interface which has two functions, `String` and `Set`. + +```go +type AddrVal struct { + addr *string +} + +func (a AddrVal) String() string { + if a.addr == nil { + return "" + } + return *a.addr +} + +func (a AddrVal) Set(s string) error { + if err := validateAddr(s); err != nil { + return err + } + *a.addr = s + return nil +} + +func validateAddr(addr string) error { + // validate address + return nil +} + +func main() { + addr := ":8080" // default value + flag.Var(AddrVal{&addr}, "addr", "address to listen on") + flag.Parse() + + fmt.Println("address: ", addr) +} + +``` diff --git a/docs/go/advanced/http.md b/docs/go/advanced/http.md index 0d3b013..9c91214 100644 --- a/docs/go/advanced/http.md +++ b/docs/go/advanced/http.md @@ -10,6 +10,8 @@ go get github.com/go-chi/chi/v5/middleware go get github.com/go-chi/cors ``` +## Basic Implementation + ```go // main.go package main @@ -241,6 +243,16 @@ func (app *Config) errorJSON(w http.ResponseWriter, err error, status ...int) er } ``` +## Adding Custom Types to Session + +```go +// main.go, before creating session +gob.Register(data.User{}) + +// to add type to session +app.Session.Put(r.Context(), "user", user) // user *data.User +``` + ## Testing ```go diff --git a/docs/go/sidebar.json b/docs/go/sidebar.json index 04fe7c6..c6726c7 100644 --- a/docs/go/sidebar.json +++ b/docs/go/sidebar.json @@ -16,6 +16,8 @@ { "text": "Go Advanced", "items": [ + {"text": "Context", "link": "/go/advanced/context"}, + {"text": "Flags", "link": "/go/advanced/flags"}, { "text": "Testing", "link": "/go/advanced/testing" }, {"text": "HTTP", "link": "/go/advanced/http"}, {"text": "RPC", "link": "/go/advanced/rpc"},