Skip to main content
The DB struct is the central type in GORM. Every query, transaction, and database operation is performed through a *DB instance.

Type definition

type DB struct {
    *Config
    Error        error
    RowsAffected int64
    Statement    *Statement
    clone        int
}

Public fields

Error
error
The last error that occurred on this DB instance. Always check this field (or the returned *DB) after finisher methods. Errors accumulate via AddError.
RowsAffected
int64
The number of rows affected by the last create, update, or delete operation. For queries it reflects the number of rows returned.

Open

func Open(dialector Dialector, opts ...Option) (db *DB, err error)
Initializes a new database session using the given dialector and optional configuration options. Open applies all options, initializes callbacks, connects the dialector, and (by default) pings the database to verify connectivity.
import (
    "gorm.io/gorm"
    "gorm.io/driver/postgres"
)

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
    log.Fatal("failed to connect to database:", err)
}
Open sorts options so that a *Config value is always applied first, before any other options.

Parameters

dialector
Dialector
required
The database driver implementation. Import a driver package (e.g., gorm.io/driver/postgres) and call its Open function to obtain a Dialector.
opts
...Option
Zero or more options. A *Config struct implements Option and is the standard way to configure GORM behaviour. Other options can modify individual config fields.

Utility methods

DB

func (db *DB) DB() (*sql.DB, error)
Returns the underlying *sql.DB connection pool. Use this to set pool parameters such as SetMaxOpenConns, SetMaxIdleConns, and SetConnMaxLifetime.
sqlDB, err := db.DB()
if err != nil {
    return err
}
sqlDB.SetMaxOpenConns(25)
sqlDB.SetMaxIdleConns(5)

WithContext

func (db *DB) WithContext(ctx context.Context) *DB
Returns a new *DB that uses the given context for all subsequent operations. Equivalent to db.Session(&Session{Context: ctx}).
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var user User
db.WithContext(ctx).First(&user, 1)

Debug

func (db *DB) Debug() *DB
Returns a new *DB with the log level set to Info, causing all SQL statements to be printed. Useful during development.
db.Debug().Where("name = ?", "jinzhu").First(&user)

Session

func (db *DB) Session(config *Session) *DB
Creates a new session from the current DB, applying all settings in *Session. This is the primary way to create scoped DB instances that inherit the current state without mutating it. See Session for full field documentation.
tx := db.Session(&gorm.Session{
    PrepareStmt: true,
    Logger:      myLogger,
})

Set / Get

func (db *DB) Set(key string, value interface{}) *DB
func (db *DB) Get(key string) (interface{}, bool)
Store and retrieve arbitrary values in the current statement’s shared settings map. Values set here are accessible to callbacks and plugins.
tx := db.Set("gorm:table_options", "ENGINE=InnoDB")
value, ok := tx.Get("gorm:table_options")

InstanceSet / InstanceGet

func (db *DB) InstanceSet(key string, value interface{}) *DB
func (db *DB) InstanceGet(key string) (interface{}, bool)
Like Set/Get, but keys are namespaced to the current *Statement pointer. This prevents key collisions when multiple statements share the same underlying settings map.

Callback

func (db *DB) Callback() *callbacks
Returns the callback manager, which lets you register, replace, or remove callbacks for the create, query, update, delete, and raw operations.
db.Callback().Create().Before("gorm:create").Register("my_plugin:before_create", func(db *gorm.DB) {
    // custom logic
})

AddError

func (db *DB) AddError(err error) error
Appends an error to db.Error. If Config.TranslateError is enabled and the dialector implements ErrorTranslator, the error is translated before being stored. Subsequent errors are chained with fmt.Errorf("%v; %w", ...). Returns the current accumulated error.

Use

func (db *DB) Use(plugin Plugin) error
Registers a plugin with GORM. Calls plugin.Initialize(db) and stores the plugin by its name. Returns ErrRegistered if a plugin with the same name is already registered.
if err := db.Use(prometheus.New(prometheus.Config{})); err != nil {
    log.Fatal(err)
}

SetupJoinTable

func (db *DB) SetupJoinTable(model interface{}, field string, joinTable interface{}) error
Configures a custom join table struct for a many-to-many relationship. The join table model can carry extra fields beyond the two foreign keys.
type UserFriend struct {
    UserID   uint
    FriendID uint
    Since    time.Time
}

db.SetupJoinTable(&User{}, "Friends", &UserFriend{})

ToSQL

func (db *DB) ToSQL(queryFn func(tx *DB) *DB) string
Executes queryFn in dry-run mode and returns the generated SQL string with all bind variables interpolated. The database is not queried.
sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {
    return tx.Model(&User{}).Where("name = ?", "jinzhu").Find(&[]User{})
})
// sql => SELECT * FROM `users` WHERE name = 'jinzhu'
ToSQL skips the default transaction wrapper. Do not rely on transaction behaviour within queryFn.

Expr

func Expr(expr string, args ...interface{}) clause.Expr
Package-level function that wraps a raw SQL fragment and its arguments into a clause.Expr. Use it anywhere GORM accepts an interface{} value to pass a SQL expression instead of a literal.
// Increment a counter without loading the record
db.Model(&product).Update("price", gorm.Expr("price * ? + ?", 0.9, 10))

Generics API — G[T]

func G[T any](db *DB, opts ...clause.Expression) Interface[T]
G[T] is GORM’s type-safe generics API, available in Go 1.18+. It wraps a *DB and exposes all CRUD and query operations as strongly-typed methods that return T or []T directly — no type assertions or pointer scanning required.
import "gorm.io/gorm"

type User struct {
    gorm.Model
    Name string
    Age  int
}

// Create a type-safe query handle for User
users := gorm.G[User](db)

// First returns (User, error) — no pointer needed
user, err := users.Where("name = ?", "jinzhu").First(ctx)

// Find returns ([]User, error)
list, err := users.Where("age > ?", 18).Order("name ASC").Find(ctx)

// Create
err = users.Create(ctx, &User{Name: "jinzhu", Age: 20})

// Update — returns (rowsAffected int, err error)
n, err := users.Where("age < ?", 18).Update(ctx, "age", 18)

// Delete
n, err = users.Where("name = ?", "old").Delete(ctx)

Interface[T]

The top-level interface returned by G[T]:
type Interface[T any] interface {
    Raw(sql string, values ...interface{}) ExecInterface[T]
    Exec(ctx context.Context, sql string, values ...interface{}) error
    CreateInterface[T]
}

ExecInterface[T]

Query execution methods returning typed results:
type ExecInterface[T any] interface {
    First(context.Context) (T, error)
    Last(ctx context.Context) (T, error)
    Take(context.Context) (T, error)
    Find(ctx context.Context) ([]T, error)
    FindInBatches(ctx context.Context, batchSize int, fc func(data []T, batch int) error) error
    Scan(ctx context.Context, r interface{}) error
    Row(ctx context.Context) *sql.Row
    Rows(ctx context.Context) (*sql.Rows, error)
}

ChainInterface[T]

Chainable query-building methods:
type ChainInterface[T any] interface {
    ExecInterface[T]
    Where(query interface{}, args ...interface{}) ChainInterface[T]
    Not(query interface{}, args ...interface{}) ChainInterface[T]
    Or(query interface{}, args ...interface{}) ChainInterface[T]
    Select(query string, args ...interface{}) ChainInterface[T]
    Omit(columns ...string) ChainInterface[T]
    Order(value interface{}) ChainInterface[T]
    Limit(offset int) ChainInterface[T]
    Offset(offset int) ChainInterface[T]
    Distinct(args ...interface{}) ChainInterface[T]
    Group(name string) ChainInterface[T]
    Having(query interface{}, args ...interface{}) ChainInterface[T]
    Joins(query clause.JoinTarget, on func(db JoinBuilder, joinTable clause.Table, curTable clause.Table) error) ChainInterface[T]
    Preload(association string, query func(db PreloadBuilder) error) ChainInterface[T]
    MapColumns(m map[string]string) ChainInterface[T]
    Scopes(scopes ...func(db *Statement)) ChainInterface[T]
    Table(name string, args ...interface{}) ChainInterface[T]
    Delete(ctx context.Context) (rowsAffected int, err error)
    Update(ctx context.Context, name string, value any) (rowsAffected int, err error)
    Updates(ctx context.Context, t T) (rowsAffected int, err error)
    Count(ctx context.Context, column string) (result int64, err error)
    Set(assignments ...clause.Assigner) SetUpdateOnlyInterface[T]
}

PreloadBuilder

Used in Preload callbacks with the generics API:
type PreloadBuilder interface {
    Select(...string) PreloadBuilder
    Omit(...string) PreloadBuilder
    Where(query interface{}, args ...interface{}) PreloadBuilder
    Not(query interface{}, args ...interface{}) PreloadBuilder
    Or(query interface{}, args ...interface{}) PreloadBuilder
    Limit(offset int) PreloadBuilder
    Offset(offset int) PreloadBuilder
    Order(value interface{}) PreloadBuilder
    LimitPerRecord(num int) PreloadBuilder  // limit per parent record (not supported for many2many)
}
G[T] requires Go 1.18 or later. The traditional *DB API continues to work in all Go versions and is not deprecated.

Build docs developers (and LLMs) love