go-starter

repository·master·Indexed 20 days ago

https://github.com/allaboutapps/go-starter

A foundational template and boilerplate for building Go applications using standard Go patterns. It includes support for generating Go types from OpenAPI/Swagger specifications, database schema diagram generation via SchemaCrawler, and database migrations using sql-migrate. The project follows standard Go project layout conventions with specific directories for internal logic (/internal), reusable packages (/pkg), and web assets (/web), and utilizes Cobra for CLI management.

Tokens
15.5K
Snippets
59
Records
96
Agent score
69%

What's inside go-starter

  1. Project structure and code organization

    master

    The project follows standard Go project layout conventions for organizing code based on reusability and visibility:

    • /cmd: Contains the main applications (entry points). Keep logic minimal here.
    • /pkg: Contains code that is intended to be imported and reused by other projects.
    • /internal: Contains code that is not intended for external reuse. Code in this directory is protected by the Go compiler and cannot be imported by outside packages.

    When deciding where to place code, ask if it should be reusable. If yes, use /pkg. If no, or if you want to explicitly prevent reuse, use /internal.

  2. Migrate Application Logic to Services (Version 25.04.0)

    master
    In version 25.04.0, application logic was moved from handlers to dedicated services. This is a BREAKING change. If your application contains custom logic within the handlers, you must move that logic into the new service layer to avoid breaking changes.
  3. Manage Database Transactions with `db|dbUtil.WithTransaction`

    master

    Instead of manually managing the lifecycle of database transactions (using db.BeginTx, db.Commit, and db.Rollback), use db|dbUtil.WithTransaction.

    This approach is safer and is enforced by a custom linter to prevent common transaction management errors. Manual management should only be used in exceptional cases where you can opt-out via linter excludes.

  4. Understand the Swagger specification composition

    master

    The final /api/swagger.yml file is an auto-generated aggregate composed of three distinct parts:

    1. Skeleton Spec: The base structure defined in /api/config/main.yml.
    2. Path Specs: Individual path definitions located in /api/paths/*.yml.
    3. Definitions: Any schema definitions located in /api/definitions/*.yml that are referenced by the skeleton or path specifications.

    When adding new endpoints or data models, ensure they are placed in the correct directory so they are included in the final generated specification.

  5. Understand the `/internal` directory structure

    master

    The /internal directory contains private application and library code that is not intended to be imported by external applications or libraries. This is enforced by the Go compiler.

    While the directory is private, it is organized into sub-packages to separate concerns. For larger projects, you can further distinguish between application-specific code (e.g., /internal/app/myapp) and shared internal code (e.g., /internal/pkg/myprivlib).

  6. Quickstart: Set up the go-starter development environment

    master

    To start developing with go-starter, use the provided docker-helper.sh to launch a Docker Compose-based development environment. This setup uses VSCode DevContainers, meaning you do not need a local Go toolchain installed on your host machine.

    Prerequisites

    # Clone your new repository, cd into it, then start the dev environment
    ./docker-helper.sh --up
  7. Migrate Data and Test Fixtures (Version 25.04.0)

    master

    In version 25.04.0, fixtures were moved to dedicated packages. This is a BREAKING change.

    • Data Fixtures: Moved from internal/data/ to internal/data/fixtures.
    • Test Fixtures: Moved from internal/test/ to internal/test/fixtures.

    Action Required: Update all imports in your project that reference the old fixture locations to point to the new fixtures sub-packages.

  8. Convert server initialization to Wire providers

    master

    To support automated dependency injection, you must move away from initializing components via methods on the Server struct (e.g., func (s *Server) InitPush() error). Instead, you must define providers following the Google Wire guidelines.

    A provider is an ordinary function that accepts necessary dependencies as input parameters and returns an initialized component. If a provider cannot reside in its dedicated package, place it in providers.go.

    Example Provider:

    func NewPush(cfg config.Server, db *sql.DB) (*push.Service, error) {
        // initialization logic
    }
    func NewPush(cfg config.Server, db *sql.DB) (*push.Service, error) {
        // ...
    }