← Back to list

Implementing Seeders in a Go API Using GORM

Seeders are essential in applications that use databases to populate initial data in test, development, or production environments. In Go…

yorni felipe bonilla paz · 2025-03-07 18:02 · 0 claps · 2.4 min read
#go #gorm #api #seeder #cod
Open on Medium ↗

Implementing Seeders in a Go API Using GORM

Seeder Go

Seeder Go

Seeders are essential in applications that use databases to populate initial data in test, development, or production environments. In Go applications using GORM, seeders automate the creation of predefined records such as user roles, permissions, locations, and other necessary configurations.

In this article, we will explain how to efficiently implement and run seeders in a Go API using GORM ORM.

Note: The installation, configuration, and architecture of this project have already been covered in a previous article: No More “It Works Locally”: Dockerizing a Go API the Right Way. Additionally, the explanation of seeders, including their advantages and disadvantages, is detailed in another article: Understanding Seeders in Applications and APIs.

Configuring Seeders in Go with GORM

To effectively organize seeders, we define a SeederManager structure that manages the execution of different seeders. Let’s see its implementation:

1. Creating the SeederManager

The SeederManager is responsible for executing specific seeders based on command-line input.

//seederManager.go
package seeder

import (
    "flag"
    "fmt"
    "os"
    "github.com/sirupsen/logrus"
    "gorm.io/gorm"
    "github.com/yornipaz/guatic_back/helpers"
)

type Seeder interface {
    Run()
}

type SeederManager struct {
    db *gorm.DB
}

// Constructor for SeederManager
func NewSeederManager(db *gorm.DB) Seeder {
    return &SeederManager{db: db}
}

2. Defining Database Models

For the seeders to work correctly, we need to define the Role and Permission database models.

//models
type Permission struct {
 ID        uint     `gorm:"primaryKey"`
 Name      string    `gorm:"unique;not null" json:"name"`

}
type Role struct {
    ID   uint   `gorm:"primaryKey"`
    Name string `gorm:"unique;not null" json:"name"`
}

3. Defining the Seeders

We map each seeder function to a specific name and load JSON files to populate the database.

var seeders = map[string]func(*gorm.DB){
    "roles": func(db *gorm.DB) {
        roles, err := helpers.DecodeJsonFile[Role]("roles")
        handleSeeder("roles", err, NewRolesSeeder(db, roles))
    },
    "permissions": func(db *gorm.DB) {
        permissions, err := helpers.DecodeJsonFile[Permission]("permissions")
        handleSeeder("permissions", err, NewPermissionSeeder(db, permissions))
    },
}

4. Implementing the JSON Decoding Function

package helpers

import (
    "encoding/json"
    "fmt"
    "os"
    "path/filepath"
)

func OpenFile(name string) (file *os.File, err error) {
    wd, err := os.Getwd()
    if err != nil {
        return file, fmt.Errorf("error getting working directory: %v", err)
    }
    pathAbs := filepath.Join(wd, os.Getenv("JSON_PATH"), name+".json")
    file, err = os.Open(pathAbs)
    return file, err
}

func DecodeJsonFile[T any](name string) (data []T, err error) {
    file, err := OpenFile(name)
    if err != nil {
        return
    }
    defer file.Close()
    decoder := json.NewDecoder(file)
    err = decoder.Decode(&data)
    return
}

5. JSON Data Files Code

roles.json

[
    { "ID": 1, "Name": "Admin" },
    { "ID": 2, "Name": "User" }
]

permissions.json

[
    { "ID": 1, "Name": "Read" },
    { "ID": 2, "Name": "Write" }
]

6. Installing Required Libraries

Before running the seeders, make sure to install GORM and Logrus if they are not yet included in your project:

go get gorm.io/gorm

go get github.com/sirupsen/logrus

7. Running a Seeder

We use command-line arguments to determine which seeder to execute:

go run main.go -seeder=roles

Best Practices

  1. Keep Seeders Modular: Avoid monolithic seeder files. Separate them by entity type (roles, users, permissions, etc.).
  2. Use JSON or YAML for Configuration: Keeps seed data maintainable.
  3. Ensure Idempotency: Seeders should not duplicate existing records when executed multiple times.
  4. Log Errors Clearly: Use logging mechanisms to track execution and seeder failures.
  5. Restrict Execution in Production: Prevent seeders from overwriting critical data in production environments.

Conclusion

Seeders in Go applications with GORM are fundamental for automating database initialization. By following best practices, keeping seeders modular, and handling errors properly, we can optimize database setup in both development and production environments.

Would you like to see a more advanced use case? Let me know! 🚀


메타데이터
post_id
ec1facf7da3c
slug
implementing-seeders-in-a-go-api-using-gorm-ec1facf7da3c
url
https://medium.com/@yfbp/implementing-seeders-in-a-go-api-using-gorm-ec1facf7da3c
canonical_url
https://medium.com/@yfbp/implementing-seeders-in-a-go-api-using-gorm-ec1facf7da3c
author_url
https://medium.com/@yfbp
status
ok
fetched_at
2026-07-20 18:07:58