Skip to main content

Std time

Stop Reset

好的,让我们详细解释一下 TickerResetStop 方法。

func (t *Ticker) Reset(d Duration)

Reset 方法用于重置 Ticker 的时间间隔。如果 Ticker 已经在运行,它会停止当前的计时并立即开始新的计时周期。

使用场景:

  • 当你需要动态调整 Ticker 的时间间隔时,可以使用 Reset 方法。
  • 例如,在某些情况下,你可能希望根据某些条件来调整定时器的间隔时间。

示例代码:

package main

import (
"fmt"
"time"
)

func main() {
// 创建一个每秒触发一次的 Ticker
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()

// 启动一个 goroutine 来处理 Ticker
go func() {
for range ticker.C {
fmt.Println("Ticker ticked")
}
}()

// 等待 3 秒
time.Sleep(3 * time.Second)

// 重置 Ticker 为每 2 秒触发一次
ticker.Reset(2 * time.Second)
fmt.Println("Ticker reset to 2 seconds")

// 再等待 6 秒
time.Sleep(6 * time.Second)
}

在这个示例中,Ticker 最初每秒触发一次。在 3 秒后,我们使用 Reset 方法将 Ticker 重置为每 2 秒触发一次。

func (t *Ticker) Stop()

Stop 方法用于停止 Ticker。一旦调用 StopTicker 将不再向其通道发送任何值,并且必须确保不再使用该 Ticker

使用场景:

  • 当你不再需要定时器时,应该调用 Stop 方法来释放相关资源。
  • 例如,在某个条件满足时,你希望停止定时器。

示例代码:

package main

import (
"fmt"
"time"
)

func main() {
// 创建一个每秒触发一次的 Ticker
ticker := time.NewTicker(1 * time.Second)

// 启动一个 goroutine 来处理 Ticker
go func() {
for range ticker.C {
fmt.Println("Ticker ticked")
}
}()

// 等待 3 秒
time.Sleep(3 * time.Second)

// 停止 Ticker
ticker.Stop()
fmt.Println("Ticker stopped")

// 再等待 3 秒以确保没有更多输出
time.Sleep(3 * time.Second)
}

在这个示例中,Ticker 每秒触发一次。在 3 秒后,我们调用 Stop 方法停止 Ticker,之后 Ticker 将不再触发。

总结

  • Reset(d Duration):重置 Ticker 的时间间隔。如果 Ticker 已经在运行,它会停止当前的计时并立即开始新的计时周期。
  • Stop():停止 Ticker,使其不再向通道发送任何值,并释放相关资源。

通过这两个方法,我们可以更灵活地控制 Ticker 的行为。


当然,以下是带有注释的 time 包常用 API 分组:

时间点相关操作

  • 获取当前时间

    • time.Now():返回当前时间。
    • time.Unix(sec int64, nsec int64) Time:返回 Unix 时间。
    • time.UnixMicro(usec int64) Time:返回 Unix 微秒时间。
    • time.UnixMilli(msec int64) Time:返回 Unix 毫秒时间。
  • 创建特定时间点

    • time.Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time:返回一个指定时间点的 Time
    • time.Parse(layout, value string) (Time, error):解析一个时间字符串。
    • time.ParseInLocation(layout, value string, loc *Location) (Time, error):在指定时区解析一个时间字符串。
  • 时间格式化和解析

    • t.Format(layout string) string:格式化时间点为字符串。
    • t.AppendFormat(b []byte, layout string) []byte:将时间点格式化并追加到字节切片。
    • time.Parse(layout, value string) (Time, error):解析一个时间字符串。
    • time.ParseInLocation(layout, value string, loc *Location) (Time, error):在指定时区解析一个时间字符串。
  • 时间点属性

    • t.Year() int:返回时间点的年份。
    • t.Month() Month:返回时间点的月份。
    • t.Day() int:返回时间点的日期。
    • t.Hour() int:返回时间点的小时。
    • t.Minute() int:返回时间点的分钟。
    • t.Second() int:返回时间点的秒。
    • t.Nanosecond() int:返回时间点的纳秒。
    • t.Weekday() Weekday:返回时间点的星期几。
    • t.ISOWeek() (year, week int):返回时间点对应的 ISO 周数和年份。
  • 时间点比较

    • t.Before(u Time) bool:判断时间点是否在另一个时间点之前。
    • t.After(u Time) bool:判断时间点是否在另一个时间点之后。
    • t.Equal(u Time) bool:判断两个时间点是否相等。
    • t.Compare(u Time) int:比较两个时间点,返回 -1、0 或 1。
  • 时间点转换

    • t.In(loc *Location) Time:返回指定时区的时间点。
    • t.Local() Time:返回本地时区的时间点。
    • t.UTC() Time:返回 UTC 时区的时间点。

持续时间相关操作

  • 创建持续时间

    • time.Duration:表示两个时间点之间经过的时间,以纳秒为单位。
    • time.ParseDuration(s string) (Duration, error):解析表示持续时间的字符串。
  • 持续时间属性

    • d.Hours() float64:返回持续时间的小时数。
    • d.Minutes() float64:返回持续时间的分钟数。
    • d.Seconds() float64:返回持续时间的秒数。
    • d.Milliseconds() int64:返回持续时间的毫秒数。
    • d.Microseconds() int64:返回持续时间的微秒数。
    • d.Nanoseconds() int64:返回持续时间的纳秒数。
  • 持续时间操作

    • d.String() string:返回持续时间的字符串表示。
    • d.Round(m Duration) Duration:将持续时间四舍五入到最接近的指定单位。
    • d.Truncate(m Duration) Duration:将持续时间截断到最接近的指定单位。
    • d.Abs() Duration:返回持续时间的绝对值。

时间点与持续时间操作

  • 时间点加减持续时间

    • t.Add(d Duration) Time:返回增加指定持续时间后的时间点。
    • t.AddDate(years int, months int, days int) Time:返回增加指定年、月、日后的时间点。
  • 计算时间间隔

    • time.Since(t Time) Duration:返回从指定时间点到现在经过的时间。
    • time.Until(t Time) Duration:返回从现在到指定时间点的时间间隔。

定时操作

  • 休眠

    • time.Sleep(d Duration):阻塞当前 goroutine 一段指定的时间。
  • 定时器

    • time.NewTimer(d Duration) *Timer:返回一个新的定时器,它会在指定的时间间隔后触发。
    • time.After(d Duration) <-chan Time:在指定的持续时间之后返回一个通道,该通道将在持续时间到期时接收到当前时间。
    • time.AfterFunc(d Duration, f func()) *Timer:在指定的持续时间之后执行一个函数。
  • Ticker

    • time.NewTicker(d Duration) *Ticker:返回一个新的 Ticker,它会以指定的时间间隔触发。
    • time.Tick(d Duration) <-chan Time:返回一个通道,该通道会以指定的间隔发送时间值。

时区相关操作

  • 时区信息

    • time.FixedZone(name string, offset int) *Location:返回一个具有固定时区偏移的 Location
    • time.LoadLocation(name string) (*Location, error):加载一个指定名称的时区。
    • time.LoadLocationFromTZData(name string, data []byte) (*Location, error):从时区数据加载一个 Location
  • 时区属性

    • t.Location() *Location:返回时间点的时区信息。
    • t.Zone() (name string, offset int):返回时间点的时区名称和偏移量。
    • t.IsDST() bool:判断时间点是否在夏令时。

序列化/反序列化

  • 二进制

    • t.MarshalBinary() ([]byte, error):将时间点编码为二进制数据。
    • t.UnmarshalBinary(data []byte) error:从二进制数据解码时间点。
  • JSON

    • t.MarshalJSON() ([]byte, error):将时间点编码为 JSON 数据。
    • t.UnmarshalJSON(data []byte) error:从 JSON 数据解码时间点。
  • Text

    • t.MarshalText() ([]byte, error):将时间点编码为文本数据。
    • t.UnmarshalText(data []byte) error:从文本数据解码时间点。
  • Gob

    • t.GobEncode() ([]byte, error):将时间点编码为 Gob 数据。
    • t.GobDecode(data []byte) error:从 Gob 数据解码时间点。

其他

  • 时间常量

    • time.Nanosecond:纳秒。
    • time.Microsecond:微秒。
    • time.Millisecond:毫秒。
    • time.Second:秒。
    • time.Minute:分钟。
    • time.Hour:小时。
  • 时间点零值

    • t.IsZero() bool:判断时间点是否为零值。

通过这种分组方式,并添加注释,可以更方便地查找和记忆不同功能的 API。希望这对你有帮助!

示例代码,及注释

当然,以下是每组 API 的示例代码及相应的注释: 当然,以下是带有注释的示例代码,其中包括每个示例的打印输出:

时间点相关操作

package main

import (
"fmt"
"time"
)

func main() {
// 获取当前时间
now := time.Now()
fmt.Println("当前时间:", now)
// 输出示例: 当前时间: 2023-10-01 15:04:05.999999999 +0800 CST m=+0.000000001

// 创建特定时间点
specificTime := time.Date(2023, time.October, 1, 12, 0, 0, 0, time.UTC)
fmt.Println("特定时间:", specificTime)
// 输出: 特定时间: 2023-10-01 12:00:00 +0000 UTC

// 解析时间字符串
parsedTime, err := time.Parse("2006-01-02 15:04:05", "2023-10-01 12:00:00")
if err != nil {
fmt.Println("解析时间错误:", err)
} else {
fmt.Println("解析时间:", parsedTime)
}
// 输出: 解析时间: 2023-10-01 12:00:00 +0000 UTC

// 时间格式化
formattedTime := now.Format("2006-01-02 15:04:05")
fmt.Println("格式化时间:", formattedTime)
// 输出示例: 格式化时间: 2023-10-01 15:04:05

// 时间点属性
fmt.Println("年份:", now.Year())
// 输出示例: 年份: 2023
fmt.Println("月份:", now.Month())
// 输出示例: 月份: October
fmt.Println("日期:", now.Day())
// 输出示例: 日期: 1
fmt.Println("小时:", now.Hour())
// 输出示例: 小时: 15
fmt.Println("分钟:", now.Minute())
// 输出示例: 分钟: 4
fmt.Println("秒:", now.Second())
// 输出示例: 秒: 5
fmt.Println("纳秒:", now.Nanosecond())
// 输出示例: 纳秒: 999999999
fmt.Println("星期几:", now.Weekday())
// 输出示例: 星期几: Sunday

// 时间点比较
anotherTime := time.Date(2023, time.October, 2, 12, 0, 0, 0, time.UTC)
fmt.Println("当前时间是否在另一个时间之前:", now.Before(anotherTime))
// 输出示例: 当前时间是否在另一个时间之前: true
fmt.Println("当前时间是否在另一个时间之后:", now.After(anotherTime))
// 输出示例: 当前时间是否在另一个时间之后: false
fmt.Println("当前时间是否等于另一个时间:", now.Equal(anotherTime))
// 输出示例: 当前时间是否等于另一个时间: false

// 时间点转换
localTime := now.Local()
utcTime := now.UTC()
fmt.Println("本地时间:", localTime)
// 输出示例: 本地时间: 2023-10-01 15:04:05.999999999 +0800 CST
fmt.Println("UTC 时间:", utcTime)
// 输出示例: UTC 时间: 2023-10-01 07:04:05.999999999 +0000 UTC
}

持续时间相关操作

package main

import (
"fmt"
"time"
)

func main() {
// 创建持续时间
duration, err := time.ParseDuration("2h30m")
if err != nil {
fmt.Println("解析持续时间错误:", err)
return
}
fmt.Println("持续时间:", duration)
// 输出: 持续时间: 2h30m0s

// 持续时间属性
fmt.Println("小时数:", duration.Hours())
// 输出: 小时数: 2.5
fmt.Println("分钟数:", duration.Minutes())
// 输出: 分钟数: 150
fmt.Println("秒数:", duration.Seconds())
// 输出: 秒数: 9000
fmt.Println("毫秒数:", duration.Milliseconds())
// 输出: 毫秒数: 9000000
fmt.Println("微秒数:", duration.Microseconds())
// 输出: 微秒数: 9000000000
fmt.Println("纳秒数:", duration.Nanoseconds())
// 输出: 纳秒数: 9000000000000

// 持续时间操作
fmt.Println("持续时间字符串表示:", duration.String())
// 输出: 持续时间字符串表示: 2h30m0s
roundedDuration := duration.Round(time.Hour)
fmt.Println("四舍五入后的持续时间:", roundedDuration)
// 输出: 四舍五入后的持续时间: 3h0m0s
truncatedDuration := duration.Truncate(time.Hour)
fmt.Println("截断后的持续时间:", truncatedDuration)
// 输出: 截断后的持续时间: 2h0m0s
absDuration := duration.Abs()
fmt.Println("绝对值持续时间:", absDuration)
// 输出: 绝对值持续时间: 2h30m0s
}

时间点与持续时间操作

package main

import (
"fmt"
"time"
)

func main() {
// 获取当前时间
now := time.Now()

// 时间点加减持续时间
addedTime := now.Add(2 * time.Hour)
fmt.Println("增加 2 小时后的时间:", addedTime)
// 输出示例: 增加 2 小时后的时间: 2023-10-01 17:04:05.999999999 +0800 CST

// 增加年、月、日
addedDate := now.AddDate(1, 2, 3)
fmt.Println("增加 1 年 2 个月 3 天后的时间:", addedDate)
// 输出示例: 增加 1 年 2 个月 3 天后的时间: 2024-12-04 15:04:05.999999999 +0800 CST

// 计算时间间隔
pastTime := now.Add(-48 * time.Hour)
durationSince := time.Since(pastTime)
durationUntil := time.Until(addedTime)
fmt.Println("距离过去时间的间隔:", durationSince)
// 输出示例: 距离过去时间的间隔: 48h0m0s
fmt.Println("距离将来时间的间隔:", durationUntil)
// 输出示例: 距离将来时间的间隔: 2h0m0s
}

定时操作

package main

import (
"fmt"
"time"
)

func main() {
// 休眠 2 秒
fmt.Println("开始休眠")
time.Sleep(2 * time.Second)
fmt.Println("休眠结束")
// 输出:
// 开始休眠
// 休眠结束

// 定时器
timer := time.NewTimer(2 * time.Second)
fmt.Println("等待定时器")
<-timer.C
fmt.Println("定时器触发")
// 输出:
// 等待定时器
// 定时器触发

// After
fmt.Println("等待 After")
<-time.After(2 * time.Second)
fmt.Println("After 触发")
// 输出:
// 等待 After
// After 触发

// AfterFunc
fmt.Println("等待 AfterFunc")
afterFunc := time.AfterFunc(2*time.Second, func() {
fmt.Println("AfterFunc 触发")
})
time.Sleep(3 * time.Second) // 确保 AfterFunc 有足够时间触发
afterFunc.Stop() // 停止 AfterFunc,如果它还没有触发
// 输出:
// 等待 AfterFunc
// AfterFunc 触发

// Ticker
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
fmt.Println("Ticker 开始")
for i := 0; i < 3; i++ {
<-ticker.C
fmt.Println("Ticker 触发", i+1)
}
fmt.Println("Ticker 结束")
// 输出:
// Ticker 开始
// Ticker 触发 1
// Ticker 触发 2
// Ticker 触发 3
// Ticker 结束
}

时区相关操作

package main

import (
"fmt"
"time"
)

func main() {
// 固定时区
fixedZone := time.FixedZone("UTC+8", 8*60*60)
fmt.Println("固定时区:", fixedZone)
// 输出: 固定时区: UTC+8

// 加载时区
location, err := time.LoadLocation("America/New_York")
if err != nil {
fmt.Println("加载时区错误:", err)
return
}
fmt.Println("加载时区:", location)
// 输出: 加载时区: America/New_York

// 时区属性
now := time.Now()
fmt.Println("当前时间的时区:", now.Location())
// 输出示例: 当前时间的时区: Local
name, offset := now.Zone()
fmt.Println("当前时间的时区名称和偏移量:", name, offset)
// 输出示例: 当前时间的时区名称和偏移量: CST 28800
fmt.Println("当前时间是否为夏令时:", now.IsDST())
// 输出示例: 当前时间是否为夏令时: false
}

序列化/反序列化

package main

import (
"encoding/json"
"fmt"
"time"
)

func main() {
// 获取当前时间
now := time.Now()

// 二进制序列化/反序列化
binaryData, err := now.MarshalBinary()
if err != nil {
fmt.Println("二进制序列化错误:", err)
return
}
var binaryTime time.Time
err = binaryTime.UnmarshalBinary(binaryData)
if err != nil {
fmt.Println("二进制反序列化错误:", err)
return
}
fmt.Println("二进制反序列化时间:", binaryTime)
// 输出示例: 二进制反序列化时间: 2023-10-01 15:04:05.999999999 +0800 CST

// JSON 序列化/反序列化
jsonData, err := json.Marshal(now)
if err != nil {
fmt.Println("JSON 序列化错误:", err)
return
}
var jsonTime time.Time
err = json.Unmarshal(jsonData, &jsonTime)
if err != nil {
fmt.Println("JSON 反序列化错误:", err)
return
}
fmt.Println("JSON 反序列化时间:", jsonTime)
// 输出示例: JSON 反序列化时间: 2023-10-01 15:04:05.999999999 +0800 CST

// 文本序列化/反序列化
textData, err := now.MarshalText()
if err != nil {
fmt.Println("文本序列化错误:", err)
return
}
var textTime time.Time
err = textTime.UnmarshalText(textData)
if err != nil {
fmt.Println("文本反序列化错误:", err)
return
}
fmt.Println("文本反序列化时间:", textTime)
// 输出示例: 文本反序列化时间: 2023-10-01 15:04:05.999999999 +0800 CST
}

其他

package main

import (
"fmt"
"time"
)

func main() {
// 时间常量
fmt.Println("纳秒:", time.Nanosecond)
// 输出: 纳秒: 1ns
fmt.Println("微秒:", time.Microsecond)
// 输出: 微秒: 1µs
fmt.Println("毫秒:", time.Millisecond)
// 输出: 毫秒: 1ms
fmt.Println("秒:", time.Second)
// 输出: 秒: 1s
fmt.Println("分钟:", time.Minute)
// 输出: 分钟: 1m0s
fmt.Println("小时:", time.Hour)
// 输出: 小时: 1h0m0s

// 时间点零值
var zeroTime time.Time
fmt.Println("时间点是否为零值:", zeroTime.IsZero())
// 输出: 时间点是否为零值: true
}

这些示例代码展示了 time 包中常用 API 的使用方法,并附带了详细的注释和输出示例,希望对你有所帮助!

实现 setTimeout setTimeInterval

在 Go 语言中,虽然没有像 JavaScript 中的 setTimeoutsetInterval 这样的内置函数,但我们可以使用 time 包中的定时器和 Ticker 来实现类似的功能。

实现 setTimeout

我们可以使用 time.AfterFunc 来实现 setTimeout,它会在指定的时间后执行一个函数。

package main

import (
"fmt"
"time"
)

// setTimeout 模拟 JavaScript 的 setTimeout
func setTimeout(f func(), delay time.Duration) *time.Timer {
return time.AfterFunc(delay, f)
}

func main() {
fmt.Println("开始")

setTimeout(func() {
fmt.Println("2 秒后执行")
}, 2*time.Second)

// 等待足够的时间以确保定时器触发
time.Sleep(3 * time.Second)
}

实现 setInterval

我们可以使用 time.Ticker 来实现 setInterval,它会在指定的间隔时间内重复执行一个函数。

package main

import (
"fmt"
"time"
)

// setInterval 模拟 JavaScript 的 setInterval
func setInterval(f func(), interval time.Duration) *time.Ticker {
ticker := time.NewTicker(interval)
go func() {
for range ticker.C {
f()
}
}()
return ticker
}

func main() {
fmt.Println("开始")

ticker := setInterval(func() {
fmt.Println("每秒执行一次")
}, 1*time.Second)

// 等待足够的时间以观察多次执行
time.Sleep(5 * time.Second)

// 停止定时器
ticker.Stop()
fmt.Println("结束")
}

取消定时器

在上述实现中,我们可以通过调用 TimerTickerStop 方法来取消定时器。

package main

import (
"fmt"
"time"
)

// setTimeout 模拟 JavaScript 的 setTimeout
func setTimeout(f func(), delay time.Duration) *time.Timer {
return time.AfterFunc(delay, f)
}

// setInterval 模拟 JavaScript 的 setInterval
func setInterval(f func(), interval time.Duration) *time.Ticker {
ticker := time.NewTicker(interval)
go func() {
for range ticker.C { // ticker.C 是ticker 一个通道,每interval会接收到一个时间值
f()
}
}()
return ticker
}

func main() {
fmt.Println("开始")

// 使用 setTimeout
timer := setTimeout(func() {
fmt.Println("2 秒后执行")
}, 2*time.Second)

// 等待 1 秒,然后取消 setTimeout
time.Sleep(1 * time.Second)
timer.Stop()
fmt.Println("setTimeout 被取消")

// 使用 setInterval
ticker := setInterval(func() {
fmt.Println("每秒执行一次")
}, 1*time.Second)

// 等待 3 秒,然后取消 setInterval
time.Sleep(3 * time.Second)
ticker.Stop()
fmt.Println("setInterval 被取消")

// 等待额外的 2 秒以确保没有更多输出
time.Sleep(2 * time.Second)
fmt.Println("结束")
}

在这个示例中,我们展示了如何使用 time.AfterFunctime.Ticker 来模拟 JavaScript 的 setTimeoutsetInterval,并且展示了如何取消这些定时器。