golang time模块

时间

  • time.Now()获取当前时间

    • 返回值是time类型
    • 默认获取的是当地时间
    • time.Now().UTC()获取格林威治时间
  • time类型

    • 实际是一个结构体
      • Unix时间地域信息组成
    • 字符串打印: 2018-11-21 11:50:39.540473 +0800 CST m=+0.000311562
      • +8000 CST 指中国标准时间
      • +0000 UTC 指格林威治时间
  • unix时间

    • 从格林威治时间1970年1月1日0时开始到现在的总秒数
time.Now().Unix()
// 总纳秒数
time.Now().UnixNano()

格式化时间

  • time类型->字符串
    • 只能用2006-01-02 15:04:05这个时间点作为格式化模板
str1 := time.Now().Format("2006-01-02 15:04:05")
str2 := time.Now().Format("2006年1月2日 15:04:05")
  • 字符串->time类型
    • 返回值是time类型
    • 获得的时间是UTC时间而不是北京时间
timestamp1, err := time.Parse("2006-01-02 15:04:05", str1)
timestamp2, err := time.Parse("2006年1月2日 15:04:05", str2)

时间长度

type Duration int64

const (
    Nanosecond Duration = 1
    Microsecond = 1000 * Nanosecond
    Millisecond = 1000 * Microsecond
    Second = 1000 * Millisecond
    Minute = 60 * Second
    Hour = 60 * Minute
)

time.ParseDuration(s string) (Duration, error)
// 减去7分钟
m,_ := time.ParseDuration("-7m")
// 加上10秒
s,_ := time.ParseDuration("10s")
  • time.Duration表示时间长度
    • 以纳秒为基数
    • 底层数据类型为int64
  • int64类型的变量不能直接和time.Duration类型相乘,需要显示转换; 常量除外
    • 不行:num * time.Second
    • 可以: time.Duration(num) * time.Second
    • 可以: 5 * time.Second

时间比较

dt := time.Date(2018, 1, 10, 0, 0, 1, 100, time.Local)
fmt.Println(time.Now().After(dt))     // true
fmt.Println(time.Now().Before(dt))    // false
fmt.Println(dt.Equal(time.Now())) // 判断两个时间点是否相等时使用Equal函数

时间计算

  • time.Add()用来获得指定时间

// 将t0加duration获取t1使用Add方法
func (t Time) Add(d Duration) Time

//一天之前
time.Now().Add(-24 * time.Hour)
// 一年前+2月后+三天前
time.Now().AddDate(-1,2,-3)
  • time.Sub()用来计算时间长度
//获取t0和t1的duration使用Sub
func (t Time) Sub(u Time) Duration

start := time.Now()
longCalculation()
end := time.Now()
delta := end.Sub(start)

超时控制

time.After

func After(d Duration) <-chan Time
// 在时间d后自动执行函数f
func AfterFunc(d Duration, f func()) *Timer
  • time.After从定义的那一行开始计时

  • 一个time.After应该只被使用一次,否则会发生死锁

  • time.After和select联合使用以实现超时

    • select中定义的time.After从select执行时开始计时,如果select在超时前再被执行则重新开始计时
      • 当外层有for循环时容易发生
      • 因此如果需要全局超时,而不是每次执行的超时,需要在for循环前定义 time.After
    • 如果select中包含default分支则超时永远执行不到
  • time.AfterFunc等待一定时间后执行函数

    • 底层启动一个goroutine执行函数
    • 可以利用返回值的Stop操作取消执行

time.Tick

  • time.Tick 是对time.NewTicker的简化
  • 不要定义在for循环内,容易造成CPU暴涨
    • 例如for range time.Tick(time.Second)
    • 这样会导致每次循环都创建一个计时goroutine
    • 应该定义在循环前
  • time.Tick 函数 仅仅在应用整个生命周期都需要时才适合
    • 否则应该使用time.NewTicker并手动stop
    • time.Tick 函数的行为很像创建一个 goroutine 在循环里面调用time.Sleep,然后在它每次醒来时发送事件
      • 如果停止监听 tick,但是计时器 goroutine 还在运行,徒劳地向一个没有 goroutine 在接收的通道中不断发送
      • 这会造成goroutine泄露
func Tick(d Duration) <-chan Time

// 定时执行任务
timer := time.Tick(time.Second)
for range timer {
	fmt.Println("hello")
}

time.NewTicker

  • 同上,不要定义在for循环内
  • 用完后记得用Stop函数关闭goroutine
func() {
	ticker := time.NewTicker(time.Second)
	defer ticker.Stop() //一定要stop
	
	for range ticker.C {
		fmt.Println("hello")
	}
}

你可能感兴趣的:(Golang)