go-migrationgo-migration
Package Reference
Documentation

Seeder

Complete package reference for the go-migration Seeder interface, Runner, and dependency system — all public methods with signatures, parameters, return types, and usage examples.

Seeder API

The seeder system lets you populate your database with test or default data. It consists of the Seeder interface, the Runner for execution, and an optional DependsOn interface for ordering.

Import path: github.com/gopackx/go-migration/seeder

For conceptual documentation, see Seeders.


Seeder Interface

Every seeder struct must implement this interface:

go
type Seeder interface {
    Run(db *sql.DB) error
}
MethodSignatureDescription
RunRun(db *sql.DB) errorExecutes the seeding logic

The Run method receives a *sql.DB connection and returns an error if seeding fails.

go
type UserSeeder struct{}

func (s *UserSeeder) Run(db *sql.DB) error {
    _, err := db.Exec(
        "INSERT INTO users (name, email) VALUES ($1, $2)",
        "Alice", "alice@example.com",
    )
    return err
}

See Defining Seeders.


seeder.AutoRegister()

Registers a seeder in the global auto-registry. Intended to be called from init() functions in seeder files, matching the pattern used by migrator.AutoRegister().

go
func AutoRegister(name string, s Seeder)
ParameterTypeDescription
namestringUnique name for this seeder
sSeederPointer to a struct implementing the Seeder interface

Panics if the name is a duplicate — fail-fast at startup.

seeders/user_seeder.go
package seeders

import (
    "database/sql"
    "github.com/gopackx/go-migration/seeder"
)

func init() {
    seeder.AutoRegister("UserSeeder", &UserSeeder{})
}

type UserSeeder struct{}

func (s *UserSeeder) Run(db *sql.DB) error {
    _, err := db.Exec(
        "INSERT INTO users (name, email) VALUES ($1, $2)",
        "Alice", "alice@example.com",
    )
    return err
}

When using migrator.Run(), auto-registered seeders are discovered automatically. Just blank-import the seeders package in your main.go.

See Running Seeders.


DependsOn Interface

Optionally implement DependsOn to declare that a seeder must run after other seeders.

go
type DependsOnProvider interface {
    DependsOn() []string
}
MethodSignatureDescription
DependsOnDependsOn() []stringReturns names of seeders that must run first

The runner performs a topological sort on the dependency graph to determine execution order.

go
type PostSeeder struct{}

func (s *PostSeeder) DependsOn() []string {
    return []string{"UserSeeder"}
}

func (s *PostSeeder) Run(db *sql.DB) error {
    _, err := db.Exec(
        "INSERT INTO posts (user_id, title) VALUES ($1, $2)",
        1, "First Post",
    )
    return err
}

Circular dependencies (A depends on B, B depends on A) cause a runtime error. Design seeders as a directed acyclic graph.

See Dependencies.


TaggedSeeder Interface

New in v1.0.0

Optionally implement TaggedSeeder to assign tags to a seeder for selective execution.

go
type TaggedSeeder interface {
    Seeder
    Tags() []string
}
MethodSignatureDescription
TagsTags() []stringReturns the tags this seeder belongs to

A seeder can have multiple tags. Only seeders implementing this interface are considered by RunByTag.

go
type DevUserSeeder struct{}

func (s *DevUserSeeder) Tags() []string {
    return []string{"development", "testing"}
}

func (s *DevUserSeeder) Run(db *sql.DB) error {
    _, err := db.Exec(
        "INSERT INTO users (name, email) VALUES ($1, $2)",
        "Dev User", "dev@example.com",
    )
    return err
}

See Seeder Tags.


RollbackableSeeder Interface

New in v1.0.0

Optionally implement RollbackableSeeder to define custom rollback logic for a seeder.

go
type RollbackableSeeder interface {
    Seeder
    Rollback(db *sql.DB) error
}
MethodSignatureDescription
RollbackRollback(db *sql.DB) errorUndoes the data inserted by Run
go
type UserSeeder struct{}

func (s *UserSeeder) Run(db *sql.DB) error {
    _, err := db.Exec(
        "INSERT INTO users (name, email) VALUES ($1, $2)",
        "Alice", "alice@example.com",
    )
    return err
}

func (s *UserSeeder) Rollback(db *sql.DB) error {
    _, err := db.Exec("DELETE FROM users WHERE email = $1", "alice@example.com")
    return err
}

runner.Rollback() returns an error if the seeder does not implement RollbackableSeeder.

See Seeder Rollback.


seeder.NewRunner()

Creates a new seeder runner bound to a database connection.

go
func NewRunner(db *sql.DB) *Runner
ParameterTypeDescription
db*sql.DBThe database connection for seeders to use

Returns: *Runner

go
import "github.com/gopackx/go-migration/seeder"

runner := seeder.NewRunner(db)

runner.Register()

Registers a seeder with the runner under a unique name.

go
func (r *Runner) Register(name string, s Seeder)
ParameterTypeDescription
namestringUnique name for this seeder
sSeederPointer to a struct implementing the Seeder interface
go
runner.Register("UserSeeder", &seeders.UserSeeder{})
runner.Register("PostSeeder", &seeders.PostSeeder{})
runner.Register("RoleSeeder", &seeders.RoleSeeder{})

The name passed to Register() is used to reference the seeder in Run() and in DependsOn() declarations.


runner.RunAll()

Executes all registered seeders. Respects dependency ordering.

go
func (r *Runner) RunAll() error

Returns: error — returns nil on success, or the first error encountered.

Seeders run sequentially. If a seeder returns an error, execution stops immediately. Seeders that completed before the failure remain applied.

go
if err := runner.RunAll(); err != nil {
    log.Fatal(err)
}

See Running Seeders.


runner.Run()

Executes a single seeder by its registered name.

go
func (r *Runner) Run(name string) error
ParameterTypeDescription
namestringThe name used in Register()

Returns: error — returns an error if the name doesn't match any registered seeder or if the seeder fails.

go
if err := runner.Run("UserSeeder"); err != nil {
    log.Fatal(err)
}

See Running Seeders.


runner.RunByTag()

New in v1.0.0

Executes all registered seeders that implement TaggedSeeder and have a matching tag.

go
func (r *Runner) RunByTag(tag string) error
ParameterTypeDescription
tagstringThe tag to match against

Returns: error — returns nil on success, or the first error encountered.

Seeders that don't implement TaggedSeeder are silently skipped. Only seeders whose Tags() method returns a slice containing the specified tag are executed.

go
if err := runner.RunByTag("development"); err != nil {
    log.Fatal(err)
}

See Seeder Tags.


runner.Rollback()

New in v1.0.0

Rolls back a specific seeder by calling its Rollback method.

go
func (r *Runner) Rollback(name string) error
ParameterTypeDescription
namestringThe name used in Register()

Returns: error — returns an error if the name doesn't match any registered seeder, if the seeder doesn't implement RollbackableSeeder, or if the rollback fails.

go
if err := runner.Rollback("UserSeeder"); err != nil {
    log.Fatal(err)
}

See Seeder Rollback.


runner.Truncate()

New in v1.0.0

Deletes all rows from a table.

go
func (r *Runner) Truncate(table string) error
ParameterTypeDescription
tablestringThe table name to truncate

Returns: error — returns nil on success, or an error if the operation fails.

Uses DELETE FROM for broad compatibility across databases.

go
if err := runner.Truncate("users"); err != nil {
    log.Fatal(err)
}

See Seeder Rollback.


seeder.CreateMany()

Inserts records in batches using multi-row INSERT statements. Defaults to DialectPostgres.

go
func CreateMany(db *sql.DB, table string, records []map[string]any, chunkSize int) error
ParameterTypeDescription
db*sql.DBThe database connection
tablestringTarget table name
records[]map[string]anySlice of records to insert
chunkSizeintRows per batch. Defaults to 500 if <= 0

Returns: error — returns nil on success, or an error with the batch index range on failure.

All records must have consistent keys. The function validates this before inserting.

go
records := []map[string]any{
    {"name": "Alice", "email": "alice@example.com"},
    {"name": "Bob", "email": "bob@example.com"},
}

if err := seeder.CreateMany(db, "users", records, 100); err != nil {
    log.Fatal(err)
}

See Batch Insert.


seeder.CreateManyWithDialect()

Inserts records in batches using dialect-specific SQL (placeholders and identifier quoting).

go
func CreateManyWithDialect(db *sql.DB, table string, records []map[string]any, chunkSize int, dialect Dialect) error
ParameterTypeDescription
db*sql.DBThe database connection
tablestringTarget table name
records[]map[string]anySlice of records to insert
chunkSizeintRows per batch. Defaults to 500 if <= 0
dialectDialectDatabase dialect (DialectPostgres, DialectMySQL, or DialectSQLite)

Returns: error — returns nil on success, or an error with the batch index range on failure.

go
records := []map[string]any{
    {"name": "Alice", "email": "alice@example.com"},
    {"name": "Bob", "email": "bob@example.com"},
}

// MySQL dialect — uses ? placeholders and `backtick` identifiers
if err := seeder.CreateManyWithDialect(db, "users", records, 100, seeder.DialectMySQL); err != nil {
    log.Fatal(err)
}

See Batch Insert.


Dialect Type

The Dialect type controls placeholder syntax and identifier quoting for batch inserts.

go
type Dialect int

const (
    DialectPostgres Dialect = iota // $1, $2 placeholders, "double quote" identifiers
    DialectMySQL                   // ?, ? placeholders, `backtick` identifiers
    DialectSQLite                  // ?, ? placeholders, "double quote" identifiers
)
ConstantPlaceholdersIdentifier Quoting
DialectPostgres$1, $2, $3"double quotes"
DialectMySQL?, ?, ?`backticks`
DialectSQLite?, ?, ?"double quotes"

See Batch Insert — Multi-Dialect Support.


Complete Example

main.go
package main

import (
    "database/sql"
    "log"

    _ "github.com/lib/pq"

    "github.com/gopackx/go-migration/seeder"
    "your-project/seeders"
)

func main() {
    db, err := sql.Open("postgres", "postgres://user:password@localhost:5432/mydb?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    runner := seeder.NewRunner(db)

    runner.Register("UserSeeder", &seeders.UserSeeder{})
    runner.Register("RoleSeeder", &seeders.RoleSeeder{})
    runner.Register("PostSeeder", &seeders.PostSeeder{})

    if err := runner.RunAll(); err != nil {
        log.Fatal(err)
    }

    log.Println("Seeding complete!")
}

Quick Reference

ComponentMethodSignatureDescription
InterfaceRunRun(db *sql.DB) errorExecute seeding logic
InterfaceDependsOnDependsOn() []stringDeclare dependencies (optional)
InterfaceTagsTags() []stringAssign tags (optional)
InterfaceRollbackRollback(db *sql.DB) errorCustom rollback logic (optional)
RegistryAutoRegisterAutoRegister(name, seeder)Register a seeder via init()
RunnerNewRunnerNewRunner(db) *RunnerCreate a runner
RunnerRegisterRegister(name, seeder)Register a seeder
RunnerRunAllRunAll() errorRun all seeders
RunnerRunRun(name) errorRun a specific seeder
RunnerRunByTagRunByTag(tag) errorRun seeders matching a tag
RunnerRollbackRollback(name) errorRoll back a specific seeder
RunnerTruncateTruncate(table) errorDelete all rows from a table
HelperCreateManyCreateMany(db, table, records, chunkSize) errorBatch insert (Postgres default)
HelperCreateManyWithDialectCreateManyWithDialect(db, table, records, chunkSize, dialect) errorBatch insert with dialect
TypeDialectDialectPostgres, DialectMySQL, DialectSQLiteDatabase dialect for batch inserts