time.NewTicket 疑问点记录:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
intChan := make(chan int, 1)
go func() {
for _ = range ticker.C {
select {
case intChan <- 1:
case intChan <- 2:
case intChan <- 3:
}
}
fmt.Println("send ending")
}()
sum := 0
for ele := range intChan {
fmt.Printf("receive element %d from intChan \n", ele)
if sum > 10 {
break
}
sum += ele
}
fmt.Printf("sum %d \n", sum)
}
输出结果:
为什么: send ending 没有输出????
我的理解是:
go func 中开启的是周期性定时器,理论上如果主协程不结束,该协程会一直运行。
也就是会一直执行for 语句,当主协程停止时,该协程自然也停止,所以不会执行send ending
合理的切片拷贝操作
// Endpoints lists the registered endpoints for the client.
func (c *Client) Endpoints() []string {
// copy the slice; protect original endpoints from being changed
// 复制片;保护原始endpoints不被更改
c.mu.RLock()
defer c.mu.RUnlock()
eps := make([]string, len(c.cfg.Endpoints))
copy(eps, c.cfg.Endpoints)
return eps
}
以上是在查看etcd 源码时的收货,注释很详细,大家可以参考着用
对互斥锁进行多次解锁
package main
import (
"fmt"
"sync"
)
func main() {
defer func() {
fmt.Println("try to recover the panic")
if p:= recover();p != nil{
fmt.Printf("recover the panic :%#v \n",p)
}
}()
var lock sync.Mutex
lock.Lock()
fmt.Println("has locked")
lock.Unlock()
fmt.Println("has unlocked")
fmt.Println("try to unlocked again")
lock.Unlock()
}
执行结果为:
has locked
has unlocked
try to unlocked again
fatal error: sync: unlock of unlocked mutex
goroutine 1 [running]:
runtime.throw(0x4d3e7a, 0x1e)
E:/language/go/sdk/go1.14.3/src/runtime/panic.go:1116 +0x79 fp=0xc000071ea8 sp=0xc000071e78 pc=0x432529
sync.throw(0x4d3e7a, 0x1e)
E:/language/go/sdk/go1.14.3/src/runtime/panic.go:1102 +0x3c fp=0xc000071ec8 sp=0xc000071ea8 pc=0x43249c
sync.(*Mutex).unlockSlow(0xc0000140a0, 0xc0ffffffff)
E:/language/go/sdk/go1.14.3/src/sync/mutex.go:196 +0xdd fp=0xc000071ef0 sp=0xc000071ec8 pc=0x46ec4d
sync.(*Mutex).Unlock(...)
E:/language/go/sdk/go1.14.3/src/sync/mutex.go:190
很奇怪,发现并没有recover住,翻阅资料得知,在GO1.8之前是可以recover住的,但是会导致重复解锁的goroutine永久阻塞,所以1.8之后对这类型的panic变成了不可恢复
工具类
时间相关
获取给定时间戳的零点
func GetZeroPointTime(data int64) time.Time {
timeStr := time.Unix(int64(data), 0).Format("2006-01-02")
loc, _ := time.LoadLocation("Local")
t, _ := time.ParseInLocation("2006-01-02", timeStr, loc)
return t
}
golang内存对齐
https://zhuanlan.zhihu.com/p/53413177
将UTC字符串时间转换成时间戳
// ConvertUTCStr 将UTC时间转换成时间戳
func ConvertUTCStr(utcStr string) (int64, error) {
stamp, err := time.ParseInLocation(time.RFC3339, utcStr, time.Local) //使用parseInLocation将字符串格式化返回本地时区时间
if err != nil {
return 0, err
}
return stamp.Unix(), nil
}
将当前时间戳转成UTC时间字符串
// CoverTs2Utc 将指定时间戳转换成 UTC 时间字符串
// 阿里云API 关于时间的参数,都可以使用该函数
func CoverTs2Utc(ts int64) (string, error) {
if ts <= 0 {
return "", fmt.Errorf("invalid timestamp:%d", ts)
}
t := time.Unix(ts, 0)
local, err := time.ParseInLocation(time.RFC3339, t.Format(time.RFC3339), time.Local)
if err != nil {
return "", fmt.Errorf("ParseInLocation failed:%s", err.Error())
}
utc := local.UTC()
utcStr := utc.Format(time.RFC3339)
return utcStr, nil
}
// 测试
func main (){
// 输出内容 2021-08-23T12:26:36Z
fmt.Println(CoverTs2Utc(time.Now().Unix()))
}