Gorm model定义: string VS *string

string vs *string

各种数据类型及对应的默认值

  • 指针类型的默认值为nil
go 复制代码
package main

import "fmt"

func main() {
	var b bool
	var i int
	var f32 float32
	var f64 float64
	var c64 complex64
	var c128 complex128
	var s string
	var a [3]int
	var sl []int
	var m map[string]int
	var p struct {
		x int
		y float64
	}
	var pStr *string

	fmt.Printf("bool: %v\n", b)          // 输出:bool: false
	fmt.Printf("int: %v\n", i)           // 输出:int: 0
	fmt.Printf("float32: %v\n", f32)     // 输出:float32: 0
	fmt.Printf("float64: %v\n", f64)     // 输出:float64: 0
	fmt.Printf("complex64: %v\n", c64)   // 输出:complex64: (0+0i)
	fmt.Printf("complex128: %v\n", c128) // 输出:complex128: (0+0i)
	fmt.Printf("string: %q\n", s)        // 输出:string: ""
	fmt.Printf("array: %v\n", a)         // 输出:array: [0 0 0]
	fmt.Printf("slice: %v\n", sl)        // 输出:slice: []
	fmt.Printf("map: %v\n", m)           // 输出:map: map[]
	fmt.Printf("struct: %+v\n", p)       // 输出:struct: {x:0 y:0}
	fmt.Printf("pointer: %v\n", pStr)    // 输出:struct: {x:0 y:0}
}

下面通过简单的案例看二者的区别。

case1: 数据表字段可以为null

建表语句

sql 复制代码
create table user
(
    id   int auto_increment primary key,
    name varchar(20) null
);

string类型

数据库表 users 对应的 结构体中 name为string类型

go 复制代码
type User struct {
    ID   int    `gorm:"column:id"`
    Name string `gorm:"column:name"`
}

插入记录

go 复制代码
package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	ID   int    `gorm:"column:id"`
	Name string `gorm:"column:name"`
}

func main() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/example?utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return
	}

	// 插入一条记录
	db.Debug().Create(&User{})

	// 读取一条数据
	var user User
	db.Debug().First(&user)
	fmt.Printf("%+v\n", user)
	fmt.Println(user.Name == "")
}

执行的 sql: 插入的 name值赋值为 空字符串''

数据库表中的情况,name为空字符串

*string类型

数据库表 users 对应的 结构体中 name为string类型

go 复制代码
type User struct {
	ID   int     `gorm:"column:id"`
	Name *string `gorm:"column:name"`
}
go 复制代码
package main

import (
    "fmt"

    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type User struct {
    ID   int     `gorm:"column:id"`
    Name *string `gorm:"column:name"`
}

func main() {
    dsn := "root:123456@tcp(127.0.0.1:3306)/example?utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        return
    }

    // 插入一条记录
    db.Debug().Create(&User{})

    // 读取一条数据
    var user User
    db.Debug().First(&user)
    fmt.Printf("%+v\n", user)
}

执行结果:

由于 name是 *string类型,未初始化默认为nil,插入时作为NULL插入,读取出来的 Name值也是nil

case2: 数据库字段不为null

建表语句

sql 复制代码
create table users
(
    id   int auto_increment primary key,
    name varchar(20) not null
);

string类型

Name为string类型

go 复制代码
type User struct {
	ID   int    `gorm:"column:id"`
	Name string `gorm:"column:name"`
}
go 复制代码
package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	ID   int    `gorm:"column:id"`
	Name string `gorm:"column:name"`
}

func main() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/example?utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return
	}

	// 插入一条记录
	db.Debug().Create(&User{})

	// 读取一条数据
	var user User
	db.Debug().First(&user)
	fmt.Printf("%+v\n", user)
}


写入、读取的都是空字符串

*string类型(重点⭐️)

go 复制代码
type User struct {
	ID   int     `gorm:"column:id"`
	Name *string `gorm:"column:name"`
}
go 复制代码
package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	ID   int     `gorm:"column:id"`
	Name *string `gorm:"column:name"`
}

func main() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/example?utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return
	}

	// 插入一条记录
	db.Debug().Create(&User{})

	// 读取一条数据
	var user User
	db.Debug().First(&user)
	fmt.Printf("%+v\n", user)
}


当 go对象类型为 *string 且为nil时,对应插入语句值为NULL,而由于数据库表定义的name字段不为NULL,故插入失败。

总结

  • 数据库字段可以null时,映射到go的数据类型应为指针类型
  • 数据库字段不可以null时,映射到go的数据类型应为非指针类型

go初学者,写的不一定正确, 如发现错误欢迎评论区交流,thanks

相关推荐
CoderMeijun12 小时前
一条SQL查询语句在MySQL中是如何执行的
mysql·sql执行流程·连接器·mysql架构·索引下推·执行器
雾行0x0017 小时前
Go 指南:一篇文章速通 Golang
go
ttwuai17 小时前
GoFrame 连接 MySQL 报错排查:parseTime、时区和 utf8mb4 怎么配
数据库·mysql·adb
辉灰笔记17 小时前
MySQL8 意外关机/误移data目录导致服务启动失败 PID报错/权限报错 修复文档
linux·数据库·mysql·centos
喜欢的名字被抢了18 小时前
MySQL核心机制:事务、锁与存储引擎
数据库·sql·mysql·教程
消失的旧时光-194319 小时前
MySQL 索引原理系列(二·补充):MySQL 为什么不用红黑树,而用 B+树?
数据库·b树·mysql·红黑树
万亿少女的梦16820 小时前
基于Spring Boot、Vue.js和MySQL的超市管理系统设计与实现
java·vue.js·spring boot·mysql·管理系统
weixin_3077791320 小时前
Linux下Docker Compose里运行的MySQL数据库故障诊断Shell脚本
linux·运维·mysql·docker·自动化
ArixBit21 小时前
用 Go 手撸 Agent 框架 #3:Agent 不是聊天机器人,手写第一个 ReAct 循环
go·agent
ArixBit21 小时前
用 Go 手撸 Agent 框架 #2:LLM 是什么——从 token 预测到 API 调用
go·agent