dousa1630 2018-11-07 22:08
浏览 27
已采纳

我必须发出数以千计的提醒,有什么办法避免每分钟发出响声吗?

I have a struct like:

type Notifications struct {
  Id int
  Start *time.Time
}

notifications := db.GetNotifications()

So now I need to send out these notifications whenever the time matches the current time.

1  2018-11-07 09:05:00
2  2018-11-07 09:05:00
3  2018-11-07 09:15:00
..

The simplest way for me to do this is with a ticker:

ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()

for {
    <-ticker.C
    alerts := []Notification
    for _, n := range notifications {
      if n.Start == // same year, month, day, hour and minute {
        alerts = append(alerts, n) 
      }
    }

    sendNotifications(alerts)
    // TODO mutate the notifications to avoid duplicatation sending
}

Is there a more efficient way to do be doing this?

What is the best way to match on the time, do I have to compare time.Now()'s attributes like year, month, day, hour and minute individually in my if statement? i.e. A notification is triggered if the year,month,day,hour and minute have been reached (seconds and beyond are ignored)

  • 写回答

1条回答 默认 最新

  • douchang8758 2018-11-08 08:04
    关注

    First things first, to compare time values, use the Time.Equal, Time.Before, and time.After methods. Comparing the individual components is not reliable at all:

    newYork, _ := time.LoadLocation("America/New_York")
    
    t1 := time.Date(2018, 11, 8, 4, 0, 0, 0, time.UTC)
    t2 := t1.In(newYork)
    
    fmt.Printf("%v == %v?
    ", t1, t2) // 2018-11-08 04:00:00 +0000 UTC == 2018-11-07 23:00:00 -0500 EST?
    
    fmt.Println(t1.Day() == t2.Day()) // false
    fmt.Println(t2.Equal(t1))         // true
    

    https://play.golang.org/p/06RcvuI_1Ha


    For the scheduling problem I would use a time.Timer.

    1. Figure out which notification is up next
    2. Set or reset the timer accordingly
      1. After the timer fires, goto 1
      2. If a notification is added, goto 1
      3. If a notification is deleted, goto 1

    Here is a sketch:

    package main
    
    import "time"
    
    func main() {
        t := time.NewTimer(0)
    
        go func() {
            for range t.C {
                nextTwo := db.GetNextNotifications(2)
    
                // Sanity check
                if time.Until(nextTwo[0].Start) > 1*time.Second {
                    // The timer went off early. Perhaps the notification has been
                    // deleted?
                    t.Reset(time.Until(nextTwo[0].Start))
                    continue
                }
    
                go send(nextTwo[0])
                t.Reset(time.Until(nextTwo[1].Start))
            }
        }()
    
        resetTimer(t) // call as required whenever a notification is added or removed
    }
    
    func resetTimer(t *time.Timer) {
        next := db.GetNextNotification()
        t.Reset(time.Until(next.Start))
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径