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

相关推荐
敲个大西瓜1 小时前
Java项目常用数据归档方式
mysql
kyriewen3 小时前
面试官让我查各部门工资最高的员工,我用AI三秒写出窗口函数,他愣了
后端·mysql·面试
小码工作室3 小时前
使用 HAVING 进行 MySQL 集合筛选
mysql
罗超驿3 小时前
18.事务的隔离性和隔离级别:MySQL面试高频考点全解析
数据库·mysql·面试
小江的记录本4 小时前
【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)
java·数据库·python·mysql·spring·面试·maven
木心术15 小时前
Windows系统下MySQL与AI工具集成方案:数据存储与调用实践
人工智能·windows·mysql
这个DBA有点耶5 小时前
SQL改写实战:子查询、CTE、窗口函数性能对比
数据库·mysql·性能优化
小江的记录本5 小时前
【Java基础】反射与注解:核心原理、自定义注解、注解解析方式(附《思维导图》+《面试高频考点清单》)
java·数据结构·python·mysql·spring·面试·maven
Java成神之路-6 小时前
深入拆解 MySQL InnoDB 隔离级别:从 MVCC 到临键锁
mysql
罗超驿6 小时前
19.告别复杂SQL!用MySQL视图把逻辑拆成“变量”式操作
数据库·mysql·面试