如何找到计时器触发的剩余时间?

huangapple go评论79阅读模式
英文:

How do I find the time remaining for a Timer to fire?

问题

我需要在x秒后运行一个函数,并且需要一些控制能力(重置计时器、停止计时器、查找执行剩余时间)。time.Timer是一个很好的选择,唯一缺少的是似乎没有提供查找剩余时间的方法。

我有哪些选择?

目前,我正在考虑以下代码:

package main

import "time"

type SecondsTimer struct {
    T       time.Duration
    C       chan time.Time
    control chan time.Duration
    running bool
}

func (s *SecondsTimer) run() {
    for s.T.Seconds() > 0 {
        time.Sleep(time.Second)
        select {
        case f := <-s.control:
            if f > 0 {
                s.T = f
            } else {
                s.running = false
                break
            }
        default:
            s.T = s.T - 1
        }
    }
    s.C <- time.Now()
}

func (s *SecondsTimer) Reset(t time.Duration) {
    if s.running {
        s.control <- t
    } else {
        s.T = t
        go s.run()
    }
}

func (s *SecondsTimer) Stop() {
    if s.running {
        s.control <- 0
    }
}

func NewSecondsTimer(t time.Duration) *SecondsTimer {
    time := SecondsTimer{t, make(chan time.Time), make(chan time.Duration), false}
    go time.run()
    return &time
}

现在我可以根据需要使用s.T.Seconds()

但是我担心会出现竞态条件和其他类似的问题。这样做是否可行,或者是否有更本地化的方法可以使用?

英文:

I need to run a function after x seconds, with some ability to control (reset the timer, stop the timer, find time remaining for execution). time.Timer is a close fit - the only thing missing is that it seems to provide no way of finding how much time is left.

What options do I have?

At the moment, I'm thinking of something like:

package main

import &quot;time&quot;

type SecondsTimer struct {
	T       time.Duration
	C       chan time.Time
	control chan time.Duration
	running bool
}

func (s *SecondsTimer) run() {
	for s.T.Seconds() &gt; 0 {
		time.Sleep(time.Second)
		select {
		case f := &lt;-s.control:
			if f &gt; 0 {
				s.T = f
			} else {
				s.running = false
				break
			}
		default:
			s.T = s.T - 1
		}
	}
	s.C &lt;- time.Now()
}
func (s *SecondsTimer) Reset(t time.Duration) {
	if s.running {
		s.control &lt;- t
	} else {
		s.T = t
		go s.run()
	}

}
func (s *SecondsTimer) Stop() {
	if s.running {
		s.control &lt;- 0
	}
}
func NewSecondsTimer(t time.Duration) *SecondsTimer {
	time := SecondsTimer{t, make(chan time.Time), make(chan time.Duration), false}
	go time.run()
	return &amp;time
}

Now I can use s.T.Seconds() as needed.

But I'm wary of race conditions and other such problems. Is this the way to go, or is there something more native I can use?

答案1

得分: 7

有一个更简单的方法。你仍然可以使用time.Timer来实现你想要的效果,只需要跟踪end time.Time即可:

type SecondsTimer struct {
    timer *time.Timer
    end   time.Time
}

func NewSecondsTimer(t time.Duration) *SecondsTimer {
    return &SecondsTimer{time.NewTimer(t), time.Now().Add(t)}
}

func (s *SecondsTimer) Reset(t time.Duration) {
    s.timer.Reset(t)
    s.end = time.Now().Add(t)
}

func (s *SecondsTimer) Stop() {
    s.timer.Stop()
}

func (s *SecondsTimer) TimeRemaining() time.Duration {
    return s.end.Sub(time.Now())
}

这样,剩余时间就很容易获取了。

英文:

There is a simpler way. You can still use a time.Timer to accomplish what you want, you just need to keep track of end time.Time:

type SecondsTimer struct {
	timer *time.Timer
	end   time.Time
}

func NewSecondsTimer(t time.Duration) *SecondsTimer {
	return &amp;SecondsTimer{time.NewTimer(t), time.Now().Add(t)}
}

func (s *SecondsTimer) Reset(t time.Duration) {
	s.timer.Reset(t)
	s.end = time.Now().Add(t)
}

func (s *SecondsTimer) Stop() {
	s.timer.Stop()
}

so time remaining is easy:

func (s *SecondsTimer) TimeRemaining() time.Duration {
	return s.end.Sub(time.Now())
}

huangapple
  • 本文由 发表于 2016年1月20日 10:37:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/34890589.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定