app
app is a simple and lightweight app lifecycle management library.
Example
Keep your main.go as simple as possible, all it's responsible for is creating the lifecycle, defining a default logger, and orchestrating setup and teardown.
main.go
package main
import (
"context"
"fmt"
"log/slog"
"gitea.auvem.com/go-toolkit/app"
)
func main() {
// Create a new lifecycle, defaulting to no printed logs
lifecycle := app.NewLifecycle().WithLogger(slog.New(slog.DiscardHandler))
defer func() {
if err := lifecycle.Teardown(); err != nil {
fmt.Println("Error during shutdown", err)
}
}()
// Encodes the lifecycle into a context to be used downstream
ctx := lifecycle.Context(context.Background())
// Off to you, call your entrypoint here.
Hello(ctx)
}
Now, let's define a basic logging module and handle loading that module.
logger.go
package main
import (
"log/slog"
"gitea.auvem.com/go-toolkit/app"
)
func ModuleLog(setDefault bool) *app.Module {
return app.NewModule("logger", app.ModuleOpts{
Setup: func(m *app.Module) error {
handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{})
if setDefault {
slog.SetDefault(handler)
}
m.Lifecycle().WithLogger(handler)
}
})
}
Logging can, however, be somewhat of a complex operation in itself, so I'd highly recommend checking out my applog project, which features tight integration with this app.
Finally, lets put our new lifecycle (and logger) to work!
hello.go
package main
import (
"context"
"gitea.auvem.com/go-toolkit/app"
)
func Hello(ctx context.Context) {
app := app.LifecycleFromContext(ctx)
if app == nil {
panic("hello must run within an app lifecycle")
}
lifecycle.Require(ModuleLog(true))
app.Logger().Info("Hello world!", "foo", "bar")
}
Description
app helps streamline core setup and teardown functions, defining dependency graphs for each module.
Languages
Go
100%