package main import ( "context" "database/sql" "fmt" "io" "os" "os/signal" "git.runcible.io/androiddrew/cookiecutter-golang-server/internal/logging" "git.runcible.io/androiddrew/cookiecutter-golang-server/internal/migrations" ) // run serves as the "entrypoint" of the application // // Operating system fundamentals are passed into run as arguments. // This makes your programs much easier to test because test code can // call run to execute your program, controlling arguments, and all // streams, just by passing different arguments. // // Value Type Description // os.Args []string The arguments passed in when executing your program. It’s also used for parsing flags. // os.Stdin io.Reader For reading input // os.Stdout io.Writer For writing output // os.Stderr io.Writer For writing error and logs // os.Getenv func(string) string For reading environment variables // os.Getwd func() (string, error) Get the working directory // // If you keep away from any global scope data, you can usually use t.Parallel() in more places, // to speed up your test suites. Everything is self-contained, so multiple calls to run don’t // interfere with each other. func run(ctx context.Context, w io.Writer, args []string) error { ctx, cancel := signal.NotifyContext(ctx, os.Interrupt) defer cancel() // Config // TODO add real config var dbPath string = "./app.db" logger := logging.InitLogging("INFO", w) logger.Info("I am alive!") full_database_path := "file:" + dbPath + "?cache=shared" logger.Debug(fmt.Sprintf("Using database path: %s", full_database_path)) db, err := sql.Open("sqlite3", full_database_path) if err != nil { return fmt.Errorf("failed to open: %s", full_database_path) } err = migrations.Migrate(db, logger) if err != nil { return err } // Initialize server // Add middleware return nil } func main() { ctx := context.Background() if err := run(ctx, os.Stdout, os.Args); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } }