Core Concepts
Registration

Registration

Registration is the foundation of go-lightning's performance. By registering models at startup, all reflection and query generation happens once, not on every database operation.

Why Registration Exists

Traditional ORMs use reflection on every query to map struct fields to database columns. This adds overhead to every operation. go-lightning takes a different approach:

  1. Register once at application startup
  2. Use cached data for all subsequent operations
  3. Minimal reflection overhead during queries

Basic Registration

import "github.com/tracewayapp/go-lightning/lit"
 
type User struct {
    Id        int
    FirstName string
    LastName  string
    Email     string
}
 
func init() {
    lit.RegisterModel[User](lit.PostgreSQL)
}

What Gets Cached

When you call RegisterModel, go-lightning creates a FieldMap containing:

FieldDescription
ColumnsMapMaps column names to field positions
ColumnKeysOrdered list of column names
HasIntIdWhether id field is an integer (for auto-increment)
InsertQueryPre-built INSERT statement
UpdateQueryPre-built UPDATE statement (without WHERE clause)
InsertColumnsColumns used in INSERT (excludes auto-increment id)
DriverDatabase driver (PostgreSQL or MySQL)

Default Naming Convention

go-lightning converts Go's CamelCase to SQL's snake_case:

Go FieldSQL Column
Idid
FirstNamefirst_name
LastNamelast_name
CreatedAtcreated_at
UserIDuser_i_d

Table names are derived from struct names with an s suffix:

  • Userusers
  • Productproducts

ID Detection

go-lightning automatically detects if your id field is an integer:

// Integer ID - uses DEFAULT in INSERT, RETURNING id (PostgreSQL) or LastInsertId (MySQL)
type User struct {
    Id   int    // HasIntId = true
    Name string
}
 
// String/UUID ID - includes id in INSERT values
type Session struct {
    Id   string  // HasIntId = false
    Data string
}

Custom Naming Strategy

For different naming conventions, use RegisterModelWithNaming:

type MyNamingStrategy struct{}
 
func (MyNamingStrategy) GetTableNameFromStructName(name string) string {
    return "tbl_" + strings.ToLower(name)
}
 
func (MyNamingStrategy) GetColumnNameFromStructName(name string) string {
    return strings.ToLower(name)
}
 
func init() {
    lit.RegisterModelWithNaming[User](lit.PostgreSQL, MyNamingStrategy{})
}

See Naming Strategies for more details.

Generated Queries Example

For a registered User struct with PostgreSQL:

INSERT Query:

INSERT INTO users (id,first_name,last_name,email) VALUES (DEFAULT,$1,$2,$3) RETURNING id

UPDATE Query (base):

UPDATE users SET id = $1,first_name = $2,last_name = $3,email = $4 WHERE

The WHERE clause is appended at runtime when you call Update().