1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| var ( ntpServers = []string{ "us.pool.ntp.org:123", "time.cloudflare.com:123", "time.windows.com:123", "time.apple.com:123", "time.google.com:123", "time.nist.gov:123", "ntp.ntsc.ac.cn:123", "time.smg.gov.mo:123", "stdtime.gov.hk:123", } )
func NewGroupVisitor[T any]() *GroupVisitor[T] { return &GroupVisitor[T]{result: make(chan T)} }
type GroupVisitor[T any] struct { wg sync.WaitGroup doneOnce sync.Once result chan T }
func (g *GroupVisitor[T]) Go(f func() (T, string, bool, error)) { g.wg.Add(1) go func() { defer g.wg.Done() if data, host, done, err := f(); done && err == nil { g.doneOnce.Do(func() { g.result <- data }) } }() }
func (g *GroupVisitor[T]) Wait(duration time.Duration) (T, error) { var empty T select { case <-time.After(duration): return empty, errors.New("request timeout") case ret := <-g.result: return ret, nil } }
func main() { g := NewGroupVisitor[*time.Time]() for _, host := range ntpServers { host := host g.Go(func() (*time.Time, string, bool, error) { respTime, err := ntp.Time(host) if err != nil { return nil, host, false, err }
return &respTime, host, true, nil }) }
clock, err := g.Wait(6 * time.Second) if err != nil { return } }
|