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

相关推荐
在未来等你4 小时前
SQL进阶之旅 Day 21:临时表与内存表应用
sql·mysql·postgresql·database·temporary-table·memory-table·sql-optimization
小Tomkk5 小时前
阿里云 RDS mysql 5.7 怎么 添加白名单 并链接数据库
数据库·mysql·阿里云
TobyMint6 小时前
DeepSeek Tools 初体验-golang实现
go
寒山李白8 小时前
MySQL复杂SQL(多表联查/子查询)详细讲解
sql·mysql·子查询·多表联查
冰橙子id8 小时前
centos7编译安装LNMP架构
mysql·nginx·架构·centos·php
玛奇玛丶8 小时前
面试官:千万级订单表新增字段怎么弄?
后端·mysql
天天摸鱼的java工程师9 小时前
从被测试小姐姐追着怼到运维小哥点赞:我在项目管理系统的 MySQL 优化实战
java·后端·mysql
Clang's Blog9 小时前
一键搭建 WordPress + MySQL + phpMyAdmin 环境(支持 PHP 版本选择 & 自定义配置)
数据库·mysql·php·wordpr
异常君10 小时前
高并发数据写入场景下 MySQL 的性能瓶颈与替代方案
java·mysql·性能优化
RestCloud10 小时前
如何通过ETLCloud实现跨系统数据同步?
数据库·数据仓库·mysql·etl·数据处理·数据同步·集成平台