You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

8.8 KiB

Declaring Models GORM simplifies database interactions by mapping Go structs to database tables. Understanding how to declare models in GORM is fundamental for leveraging its full capabilities.

Declaring Models Models are defined using normal structs. These structs can contain fields with basic Go types, pointers or aliases of these types, or even custom types, as long as they implement the Scanner and Valuer interfaces from the database/sql package

Consider the following example of a User model:

type User struct { ID uint // Standard field for the primary key Name string // A regular string field Email *string // A pointer to a string, allowing for null values Age uint8 // An unsigned 8-bit integer Birthday *time.Time // A pointer to time.Time, can be null MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings ActivatedAt sql.NullTime // Uses sql.NullTime for nullable time fields CreatedAt time.Time // Automatically managed by GORM for creation time UpdatedAt time.Time // Automatically managed by GORM for update time ignored string // fields that aren't exported are ignored } In this model:

Basic data types like uint, string, and uint8 are used directly. Pointers to types like *string and *time.Time indicate nullable fields. sql.NullString and sql.NullTime from the database/sql package are used for nullable fields with more control. CreatedAt and UpdatedAt are special fields that GORM automatically populates with the current time when a record is created or updated. Non-exported fields (starting with a small letter) are not mapped In addition to the fundamental features of model declaration in GORM, it’s important to highlight the support for serialization through the serializer tag. This feature enhances the flexibility of how data is stored and retrieved from the database, especially for fields that require custom serialization logic, See Serializer for a detailed explanation

Conventions Primary Key: GORM uses a field named ID as the default primary key for each model.

Table Names: By default, GORM converts struct names to snake_case and pluralizes them for table names. For instance, a User struct becomes users in the database, and a GormUserName becomes gorm_user_names.

Column Names: GORM automatically converts struct field names to snake_case for column names in the database.

Timestamp Fields: GORM uses fields named CreatedAt and UpdatedAt to automatically track the creation and update times of records.

Following these conventions can greatly reduce the amount of configuration or code you need to write. However, GORM is also flexible, allowing you to customize these settings if the default conventions don’t fit your requirements. You can learn more about customizing these conventions in GORM’s documentation on conventions.

gorm.Model GORM provides a predefined struct named gorm.Model, which includes commonly used fields:

// gorm.Model definition type Model struct { ID uint gorm:"primaryKey" CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt gorm:"index" } Embedding in Your Struct: You can embed gorm.Model directly in your structs to include these fields automatically. This is useful for maintaining consistency across different models and leveraging GORM’s built-in conventions, refer Embedded Struct

Fields Included:

ID: A unique identifier for each record (primary key). CreatedAt: Automatically set to the current time when a record is created. UpdatedAt: Automatically updated to the current time whenever a record is updated. DeletedAt: Used for soft deletes (marking records as deleted without actually removing them from the database). Advanced Field-Level Permission Exported fields have all permissions when doing CRUD with GORM, and GORM allows you to change the field-level permission with tag, so you can make a field to be read-only, write-only, create-only, update-only or ignored

NOTE ignored fields won’t be created when using GORM Migrator to create table

type User struct { Name string gorm:"<-:create" // allow read and create Name string gorm:"<-:update" // allow read and update Name string gorm:"<-" // allow read and write (create and update) Name string gorm:"<-:false" // allow read, disable write permission Name string gorm:"->" // readonly (disable write permission unless it configured) Name string gorm:"->;<-:create" // allow read and create Name string gorm:"->:false;<-:create" // createonly (disabled read from db) Name string gorm:"-" // ignore this field when write and read with struct Name string gorm:"-:all" // ignore this field when write, read and migrate with struct Name string gorm:"-:migration" // ignore this field when migrate with struct } Creating/Updating Time/Unix (Milli/Nano) Seconds Tracking GORM use CreatedAt, UpdatedAt to track creating/updating time by convention, and GORM will set the current time when creating/updating if the fields are defined

To use fields with a different name, you can configure those fields with tag autoCreateTime, autoUpdateTime

If you prefer to save UNIX (milli/nano) seconds instead of time, you can simply change the field’s data type from time.Time to int

type User struct { CreatedAt time.Time // Set to current time if it is zero on creating UpdatedAt int // Set to current unix seconds on updating or if it is zero on creating Updated int64 gorm:"autoUpdateTime:nano" // Use unix nano seconds as updating time Updated int64 gorm:"autoUpdateTime:milli"// Use unix milli seconds as updating time Created int64 gorm:"autoCreateTime" // Use unix seconds as creating time } Embedded Struct For anonymous fields, GORM will include its fields into its parent struct, for example:

type Author struct { Name string Email string }

type Blog struct { Author ID int Upvotes int32 } // equals type Blog struct { ID int64 Name string Email string Upvotes int32 } For a normal struct field, you can embed it with the tag embedded, for example:

type Author struct { Name string Email string }

type Blog struct { ID int Author Author gorm:"embedded" Upvotes int32 } // equals type Blog struct { ID int64 Name string Email string Upvotes int32 } And you can use tag embeddedPrefix to add prefix to embedded fields’ db name, for example:

type Blog struct { ID int Author Author gorm:"embedded;embeddedPrefix:author_" Upvotes int32 } // equals type Blog struct { ID int64 AuthorName string AuthorEmail string Upvotes int32 } Fields Tags Tags are optional to use when declaring models, GORM supports the following tags: Tags are case insensitive, however camelCase is preferred. If multiple tags are used they should be separated by a semicolon (;). Characters that have special meaning to the parser can be escaped with a backslash () allowing them to be used as parameter values.

Tag Name Description column column db name type column data type, prefer to use compatible general type, e.g: bool, int, uint, float, string, time, bytes, which works for all databases, and can be used with other tags together, like not null, size, autoIncrement… specified database data type like varbinary(8) also supported, when using specified database data type, it needs to be a full database data type, for example: MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT serializer specifies serializer for how to serialize and deserialize data into db, e.g: serializer:json/gob/unixtime size specifies column data size/length, e.g: size:256 primaryKey specifies column as primary key unique specifies column as unique default specifies column default value precision specifies column precision scale specifies column scale not null specifies column as NOT NULL autoIncrement specifies column auto incrementable autoIncrementIncrement auto increment step, controls the interval between successive column values embedded embed the field embeddedPrefix column name prefix for embedded fields autoCreateTime track current time when creating, for int fields, it will track unix seconds, use value nano/milli to track unix nano/milli seconds, e.g: autoCreateTime:nano autoUpdateTime track current time when creating/updating, for int fields, it will track unix seconds, use value nano/milli to track unix nano/milli seconds, e.g: autoUpdateTime:milli index create index with options, use same name for multiple fields creates composite indexes, refer Indexes for details uniqueIndex same as index, but create uniqued index check creates check constraint, eg: check:age > 13, refer Constraints <- set field’s write permission, <-:create create-only field, <-:update update-only field, <-:false no write permission, <- create and update permission -> set field’s read permission, ->:false no read permission

  • ignore this field, - no read/write permission, -:migration no migrate permission, -:all no read/write/migrate permission comment add comment for field when migration Associations Tags GORM allows configure foreign keys, constraints, many2many table through tags for Associations, check out