Mastering GORM: A Beginner’s Guide to Go ORM CRUD Operations
This article walks through setting up GORM in a Go project, covering dependency management, database initialization, model definition, and practical examples of select, insert, update, delete, raw SQL execution, and transaction handling with detailed code snippets.
Introduction
GORM is a popular ORM library written in Go that offers comprehensive documentation and developer-friendly APIs for mainstream databases. The author, while consolidating knowledge of Go’s foundational libraries, chose GORM for its popularity and shares practical experiences for beginners.
go.mod Dependency
Add the GORM module to your project: github.com/jinzhu/gorm v1.9.16 Running go mod tidy automatically resolves and adds required dependencies to go.mod.
Import Statements
import (
"fmt"
"funtester/base"
"funtester/futil"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"log"
"testing"
"time"
)Database Initialization
The following init function opens a MySQL connection, configures the connection pool, and auto‑migrates the schema.
func init() {
var err error
drive, err = gorm.Open("mysql", "root:root123456@(localhost:3306)/funtester?charset=utf8&parseTime=true")
if err != nil {
fmt.Println(err)
log.Fatalln("mysql conntect err")
}
drive.DB().SetMaxOpenConns(200)
drive.DB().SetConnMaxLifetime(10 * time.Second)
drive.DB().SetConnMaxIdleTime(10 * time.Second)
drive.DB().SetMaxIdleConns(20)
// AutoMigrate creates missing tables, columns, indexes, and foreign keys but does not drop unused columns.
drive.AutoMigrate(&Funtester{})
}Model Definition
type Funtester struct {
gorm.Model
Name string
Age int
}The corresponding MySQL table created by AutoMigrate looks like:
DROP TABLE IF EXISTS `funtesters`;
CREATE TABLE `funtesters` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int unsigned DEFAULT NULL,
`created_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_funtesters_deleted_at` (`deleted_at`)
) ENGINE=InnoDB AUTO_INCREMENT=241861 DEFAULT CHARSET=utf8mb3;
SET FOREIGN_KEY_CHECKS = 1;Source of gorm.Model:
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}Select Queries
Two example test functions demonstrate basic and complex query patterns.
func TestSelect1(t *testing.T) {
var f Funtester
drive.First(&f, 34) // primary key = 34
last := drive.Last(&f, "age != 1") // add condition
fmt.Printf("查询到记录数 %d "+base.LINE, last.RowsAffected)
fmt.Println(f)
take := drive.Take(&f) // no explicit order
fmt.Println(take.RowsAffected)
}
func TestSelect2(t *testing.T) {
var fs []Funtester
var f Funtester
drive.Where("id = ?", 45).First(&f) // alternative syntax
find := drive.Where("name like ?", "fun%").Find(&fs).Limit(10).Order("id") // chained conditions
rows, _ := find.Rows()
defer rows.Close()
for rows.Next() {
var ff Funtester
drive.ScanRows(rows, &ff)
fmt.Println(ff.Age, ff.Name)
}
var f1 Funtester
drive.Where("name LIKE ?", "fun").Or("id = ?", 123).First(&f1)
fmt.Println(f1)
}Update
func TestUpdate(t *testing.T) {
drive.Model(&Funtester{}).Where("id = ?", 241860).Update("name", base.FunTester+"3")
}Insert
GORM supports creating records, selecting specific fields, and omitting fields. Batch insert is not supported in the used version.
func TestInsert(t *testing.T) {
value := &Funtester{Name: "FunTester" + futil.RandomStr(10)}
drive.Create(value)
drive.Select("name", "age").Create(value) // only name and age
futil.Sleep(1)
drive.Omit("age", "name").Create(&Funtester{Name: "fds", Age: 122}) // omit fields
fs := []Funtester{{Name: "fs" + futil.RandomStr(10), Age: 12}, {Name: "fs" + futil.RandomStr(10), Age: 12}}
drive.Create(&fs) // not supported in this version
}Delete
func TestDelete(t *testing.T) {
db := drive.Where("id = ?", 241859).Delete(&Funtester{})
fmt.Println(db.RowsAffected)
}Executing Raw SQL
func TestSql(t *testing.T) {
var funtester []Funtester
scan := drive.Raw("select * from funtesters where id > 333 limit 10").Scan(&funtester)
fmt.Println(scan.RowsAffected)
fmt.Println(funtester)
}Transactions & Rollback
func TestRollBack(t *testing.T) {
funtester := Funtester{Name: base.FunTester, Age: 32232}
begin := drive.Begin()
err := begin.Create(&funtester).Error
if err != nil {
begin.Rollback()
return
}
begin.Commit()
}Conclusion
The basic usage of GORM—including connection setup, model definition, CRUD operations, raw SQL execution, and transaction handling—has been covered. Future articles will explore performance testing with GORM.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
