mysql中time_zone的作用,以及为什么要配置本地时区和db时区

mysql中time_zone的作用,以及为什么要配置本地时区和db时区 1. mysql中time_zone的作用 mysql中time_zone的作用,就是用来设置时区的(废话),time_zone影响TIMESTAMP类型和NOW等函数的值,但并不影响DATETIME类型和DATE类型。 因为TIMESTAMP存储的时时间戳,当用户发送过来一个时间如“2023-12-11 10:41:18”,那么mysql会将其时间戳,这个时间就是按time_zone设置的时区来解析的,然后转换成时间戳保存, 在给用户查询时在通过时区转换会时间串。 DATETIME类型不是时间戳,存入时是“2023-12-11 10:41:18”,查询时也是“2023-12-11 10:41:18”,不会做转换,也和时区无关 2. 为什么要配置本地时区和db时区 本地时区是给mysql驱动使用,并不会影响mysql的时区,只会影响mysql驱动的解析, db时区是mysql的时区,会影响mysql的时区,会影响mysql的查询结果。 本地时区作用 在读取到mysql发来的时间,go会按照本地时区来解析,转换为time.Time类型mysql按照数据库time_zone返回时间串后,go并不知道用哪个时区来解析这个时间串,所以需要设置本地时区。 本在写入time.Time类型时,go会把time.Time转换为本地时区发送给mysql 比如设置本地时区为“Asia/Shanghai” root:root@tcp(127.0.0.1:3306)/db?charset=utf8&loc=Asia%2FShanghai&parseTime=true通过loc参数来这设置 同时设置本地和数据库时区 root:root@tcp(127.0.0.1:3306)/db?charset=utf8&loc=Asia%2FShanghai&parseTime=true&time_zone=%27%2B8%3A00%27 dsn上的参数有的是给数据库驱动使用,有的是给mysql使用,具体可参阅mysql驱动的DSN

<span title='2023-12-11 10:41:18 +0800 +0800'>十二月 11, 2023</span>

Viper读取自定义远程配置

实现viper.remoteConfigFactory接口 type remoteConfigProvider struct{} //这个接口是在第一次读取远程配置时调用,viper.ReadRemoteConfig() func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) { log.Println("Getting config from remote", rp) r := bytes.NewReader([]byte("{\"a\":1}")) time.Sleep(time.Second) return r, nil } //这个接口是在客户端调用viper.WatchRemoteConfig(), 只监听一次变化 func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) { //这里写你获取配置的方法 log.Println("Watching config from remote", rp) s := fmt.Sprintf(`{"app":{"name":"test","version":%d}}`, time.Now().Unix()) r := bytes.NewReader([]byte(s)) time.Sleep(time.Second) return r, nil } //这个接口是在客户端调用viper.GetViper().WatchRemoteConfigOnChannel()时,监听多次变化 func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) { log.Println("Watching Channel config from remote", rp) ch := make(chan *viper.RemoteResponse) go func() { //defer close(ch) viper里面使用死循环来处理,如果关闭管道会返回nil, 而viper没有处理,会报painc,所以不用关闭,viper是想让你在整个生命周期都监听 //这里写你获取配置的方法 for i := 0; ; i++ { ch <- &viper.RemoteResponse{ Value: []byte(fmt.Sprintf(`{"app":{"name":"test","version":%d}}`, time.Now().Unix())), } time.Sleep(time.Second) } }() return ch, nil } 设置viper必要参数 func init() { viper.RemoteConfig = remoteConfigProvider{} //把我们写的provider设置好,否则监听不会生效 viper.SupportedRemoteProviders = []string{"app"} //这里名称需要设置好,和下面添加的名称需要一致 } 使用viper viper.SetConfigType("json") //需要和返回的数据格式一致,不然无法解析 viper.AddRemoteProvider("app", ":8080", "/aabb/cc") //app就是上面的SupportedRemoteProviders,viper内部会校验是否包含,后面两个参数根据自己的需求来填写 viper.ReadRemoteConfig() //加载远程配置 // viper.WatchRemoteConfig() //一次性监听配置,阻塞 viper.GetViper().WatchRemoteConfigOnChannel() //一直监听,非阻塞

<span title='2023-09-15 15:56:44 +0800 +0800'>九月 15, 2023</span>

go 编译指令build

go:build 是 Go 1.17 版本中引入的一个构建标记,用于根据不同的条件控制代码的编译。go:build 格式如//go:build <标记表达式>, 1.17之前使用+build的方式,这里我们介绍更强大的的go:build. 表达式可以包含由 ||、&& 和 ! 运算符和括号组合的选项,含义与 Go 语言中相同. 构建约束可以出现在任何类型的源文件中(不仅仅是 Go 文件),但是它们必须出现在文件的顶部附近,仅由空行和其他行注释分隔。这些规则意味着在 Go 文件中,构建约束必须出现在包声明之前。 例如,下面的构建约束将约束一个文件在满足“linux”和“386”约束条件或在满足“darwin”条件且未满足“cgo”条件时进行构建://go:build (linux && 386) || (darwin && !cgo) 自定义tag //go:build atest 当我们使用go build -tags atest的情况下会编译此文件,否则不会编译 控制go版本 //go:build go1.17 指定当前文件>=go1.17才编译 //go:build go1.17 && go1.20 版本>= go1.17 并且<= go1.20

<span title='2023-03-07 10:50:47 +0800 +0800'>三月 7, 2023</span>

go 编译指令Linkname

go:linkename是go的编译指令,可以在一个包中使用另一个包中的非导出函数或变量 具体使用方法举例 在pkg1包中有个未导出的函数add package pkg1 func add(a, b int) int { return a + b } 在pkg2中想要使用pkg1.add,正常来说add开头是小写是不能被另一个包使用的,这时候我们想要在另一个包中使用就有两种方法: 在pkg1中定义一个可以导出的函数,这种就是在写个Add函数包裹一下,这种就不举例了 在pkg2中使用linkname编译指令修改函数或变量的名称和可见性(不太建议) 这里我们举例第二种 package pkg2 import ( _ "goasm/pkg1" //需要引入pkg1, 让pkg1参与代码编译,否则编译器找不到, 这句也可以写在别的文件中,只要让pkg1参与编译就行, relocation target goasm/pkg1.add not defined _ "unsafe" //编译器要求导入unsafe包,否则不能使用linkname指令 ) //下面就是linkname编译指令使用方法, 在函数声明上添加注释, 其中pkg1_add是函数名称, goasm/pkg1.add 是要连接的函数, 这句指令的效果就是,调用pkg1_add就是在调用goasm/pkg1包中的add函数 //go:linkname pkg1_add goasm/pkg1.add func pkg1_add(a, b int) int func Add2(a, b int) int { return pkg1_add(a, b) } 总结: go:linkname的使用是依赖于编译器的实现,因此使用时需要慎重考虑其可维护性和可移植性。 总之了解就好,不是迫不得已不要真的使用

<span title='2023-02-24 14:35:25 +0800 +0800'>二月 24, 2023</span>