编辑
2023-10-12
后端
00
请注意,本文编写于 575 天前,最后修改于 575 天前,其中某些信息可能已经过时。

报错如下

go
sql: Scan error on column index 0, name "created_at": unsupported Scan, storing driver.Value type []uint8 into type *time.Time

解决方法 在mysql dsn加上

parseTime=true

解决

一.gorm连接mysql数据库

gorm支持多种数据库,这里主要介绍mysql,连接mysql主要有两个步骤:

配置DSN (Data Source Name)

使用gorm.Open连接数据库

  1. 配置DSN (Data Source Name)

gorm库使用dsn作为连接数据库的参数,dsn翻译过来就叫数据源名称,用来描述数据库连接信息。一般都包含数据库连接地址,账号,密码之类的信息。

DSN格式:

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]

mysql连接dsn例子:

go
//mysql dsn格式 //涉及参数: //username 数据库账号 //password 数据库密码 //host 数据库连接地址,可以是Ip或者域名 //port 数据库端口 //Dbname 数据库名 username:password@tcp(host:port)/Dbname?charset=utf8&parseTime=True&loc=Local //填上参数后的例子 //username = root //password = 123456 //host = localhost //port = 3306 //Dbname = tizi365 //后面K/V键值对参数含义为: // charset=utf8 客户端字符集为utf8 // parseTime=true 支持把数据库datetime和date类型转换为golang的time.Time类型 // loc=Local 使用系统本地时区 root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local //gorm 设置mysql连接超时参数 //开发的时候经常需要设置数据库连接超时参数,gorm是通过dsn的timeout参数配置 //例如,设置10秒后连接超时,timeout=10s //下面是完成的例子 root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local&timeout=10s //设置读写超时时间 // readTimeout - 读超时时间,0代表不限制 // writeTimeout - 写超时时间,0代表不限制 root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local&timeout=10s&readTimeout=30s&writeTimeout=60s
  1. 使用gorm.Open连接数据库 有了上面配置的dsn参数,就可以使用gorm连接数据库,下面是连接数据库的例子
go
package main import ( "gorm.io/driver/mysql" "gorm.io/gorm" ) func main() { //配置MySQL连接参数 username := "root" //账号 password := "123456" //密码 host := "127.0.0.1" //数据库地址,可以是Ip或者域名 port := 3306 //数据库端口 Dbname := "tizi365" //数据库名 timeout := "10s" //连接超时,10秒 //拼接下dsn参数, dsn格式可以参考上面的语法,这里使用Sprintf动态拼接dsn参数,因为一般数据库连接参数,我们都是保存在配置文件里面,需要从配置文件加载参数,然后拼接dsn。 dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout) //连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。 db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("连接数据库失败, error=" + err.Error()) } //延时关闭数据库连接 defer db.Close() }
  1. gorm调试模式 为了方便调试,了解gorm操作到底执行了怎么样的sql语句,开发的时候需要打开调试日志,这样gorm会打印出执行的每一条sql语句。

使用Debug函数执行查询即可 例子:

go
result := db.Debug().Where("username = ?", "tizi365").First(&u)

二.gorm连接池 在高并发实践中,为了提高数据库连接的使用率,避免重复建立数据库连接带来的性能消耗,会经常使用数据库连接池技术来维护数据库连接。 gorm自带了数据库连接池使用非常简单只要设置下数据库连接池参数即可。

数据库连接池使用例子: 定义tools包,负责数据库初始化工作

go
//定义一个工具包,用来管理gorm数据库连接池的初始化工作。 package tools //定义全局的db对象,我们执行数据库操作主要通过他实现。 var _db *gorm.DB //包初始化函数,golang特性,每个包初始化的时候会自动执行init函数,这里用来初始化gorm。 func init() { ...忽略dsn配置,请参考上面例子... // 声明err变量,下面不能使用:=赋值运算符,否则_db变量会当成局部变量,导致外部无法访问_db变量 var err error //连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。 _db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("连接数据库失败, error=" + err.Error()) } sqlDB, _ := db.DB() //设置数据库连接池参数 sqlDB.SetMaxOpenConns(100) //设置数据库连接池最大连接数 sqlDB.SetMaxIdleConns(20) //连接池最大允许的空闲连接数,如果没有sql任务需要执行的连接数大于20,超过的连接会被连接池关闭。 } //获取gorm db对象,其他包需要执行数据库查询的时候,只要通过tools.getDB()获取db对象即可。 //不用担心协程并发使用同样的db对象会共用同一个连接,db对象在调用他的方法的时候会从数据库连接池中获取新的连接 func GetDB() *gorm.DB { return _db }

使用例子:

go
package main //导入tools包 import tools func main() { //获取DB db := tools.GetDB() //执行数据库查询操作 u := User{} //自动生成sql: SELECT * FROM `users` WHERE (username = 'tizi365') LIMIT 1 db.Where("username = ?", "tizi365").First(&u) }

注意:使用连接池技术后,千万不要使用完db后调用db.Close关闭数据库连接,这样会导致整个数据库连接池关闭,导致连接池没有可用的连接。

更多使用

go
package main import ( "fmt" //_ "github.com/go-sql-driver/mysql" //"github.com/jinzhu/gorm" "gorm.io/driver/mysql" "gorm.io/gorm" ) type Students struct { gorm.Model Username string `gorm:"type:varchar(20);not null " ` Password string `gorm:"type:varchar(500);not null" ` Age int `gorm:"type:int;DEFAULT:18" ` } func main() { // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情 dsn := "luffyapi:Luffy123?@tcp(127.0.0.1:3306)/luffyapi?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { fmt.Println("连接数据库出错:", err) } db.AutoMigrate(&Students{}) user := Students{Username: "Jinzhu", Age: 18, Password: "123456"} result := db.First(&user) fmt.Println(result) db.Take(&user) //result := db.Create(&user) // 通过数据的指针来创建 //fmt.Println(result) }

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!