再谈golang的sql链接dsn
1. golang的time类型其中有一个field为loc *Location。这一点是golang和java不一样的地方
2. 这是dsn的常见golang设置,这里说明下其中每个字段的含义
root:root@tcp(127.0.0.1:3306)/user?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai&time_zone=%27%2B08%3A00%27
1. parseTime 是否将date,datetime,timestamp 等时间类型直接转换成golang 的model中的time.Time类型
2. time_zone,这个是设置当前session的时区。对timestamp类型的mysql数据,直接按照time_zone中设置的时区转换后给程序,这个转换是mysql做的,还不是驱动做的。其他类型的时间数据不会转换时区,返回的还是原来的字符串
3. loc=Asia%2FShanghai。这个是和java不一样的地方,java没有这个field。这个loc就是对应golang的time类型其中有一个field为loc *Location这个字段的。就是为了程序员自己在代码中进行时区转换使用的。例如:
3.1 本来数据库字段是datetime类型。数据库是utc时区。插入datetime类型时候,选择的是now().因此数据库写入的就是utc的时区时间。此时parseTime=true&loc=Asia%2FShanghai的话,就会导致dao层的model的time.Time 类型的loc表示是+8时区的。也就是表示这个时间是+8区的时间。
此时程序员进行程序转换:
var cstSh, _ = time.LoadLocation("Asia/Shanghai") // 上海 r := users[0].CreateTime.In(cstSh).Format("2006-01-02 15:04:05")
将不会有任何变化,数据库的时间在程序中还是会认为是+8时区的时间
3.2 如果loc不写,此时读取出来的time.Time的loc为utc时区。此时还是进行时区转换时:
var cstSh, _ = time.LoadLocation("Asia/Shanghai") // 上海
r := users[0].CreateTime.In(cstSh).Format("2006-01-02 15:04:05")
就会将utc时间转换为+8时区时间
3.3 也就是本身datetime类型的数据,读出来的time.Time一定是数据库的时间。这一点没有疑问。但是这个附带的loc的值,是由dsn的loc决定的。如果程序员不主动进行时区转换,那么这个时间一定是数据库存储的时间,如果代码中不主动进行时区转换,而是直接使用time.Time的话,这个loc完全没有使用场景。因为本身就不关注field为loc *Location这个内容。
4. 矛盾和出路
4.1 now()的使用决定了数据库的datetime类型的字段值一定是mysql的时区一致
4.2 如果增加了dsn的timezone字段,仅能自动修改掉timestamp类型的时间。但是该时间的loc还是由dsn的链接决定的。同时存在datetime和timestamp将导致两难,举例如下:
1. mysql是utc时间
2. dsn= parseTime=true&loc=Asia%2FShanghai&time_zone=%27%2B08%3A00%27
3. createtime = datetime。 modifytime = timestamp
4. 读取的createtime对应的时间的loc=+8时区,但是值是utc时间的值。读取的modifytime的值是+8时区的值,但是loc=+8时区。也就是modifytime的时间是正确的了,但是createtime的时间和时区对不上
5. 使用dsn= parseTime=true&loc=Asia%2FShanghai,不使用time_zone
6. 这种情况下,读取的createtime对应的时间的loc=+8时区,但是值是utc时间的值。读取的modifytime的值是utc时间的值,对应的时间的loc=+8时区。依然是错误的
7. 数据库now语句的使用,导致loc设置为和数据库的时区不一致的情况下,datetime类型值和时区一定存在矛盾。因为时区是loc决定的,值是数据库存储的值决定的。
8.因此loc的值必须和数据库的时区一致,而设置time_zone将没有什么意义,因为time_zone结合和时区不一样的loc的值,仅能将timestamp的值修改都正确。但是对使用now的其他字段的值,将无计可施。