Golang / GoLang System Architecture and Testing Interview Questions
How do you manage the full lifecycle of a Go microservice from startup to shutdown?
A production Go service follows a structured lifecycle: configuration validation, dependency initialisation, readiness signalling, traffic serving, graceful shutdown on signal, and cleanup. Each phase must handle failures correctly.
func main() { // Phase 1: load and validate config â fail fast cfg, err := config.Load() if err != nil { log.Fatalf("invalid config: %v", err) } // Phase 2: initialise dependencies logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ Level: cfg.LogLevel, })) slog.SetDefault(logger) db, err := database.Open(cfg.Database) if err != nil { log.Fatalf("database: %v", err) } defer db.Close() // Phase 3: build services userRepo := postgres.NewUserRepository(db) userSvc := service.NewUserService(userRepo) router := api.NewRouter(userSvc) // Phase 4: start server srv := &http.Server{ Addr: fmt.Sprintf(":%d", cfg.Port), Handler: router, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } errCh := make(chan error, 1) go func() { slog.Info("server starting", "port", cfg.Port) if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { errCh <- err } }() // Phase 5: wait for shutdown or error sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) select { case err := <-errCh: slog.Error("server error", "err", err) case sig := <-sigCh: slog.Info("shutdown signal", "signal", sig) } // Phase 6: graceful shutdown shutdownCtx, cancel := context.WithTimeout(context.Background(), 25*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { slog.Error("shutdown error", "err", err) } slog.Info("service stopped cleanly") }
More Related questions...