Как преобразовать переменную time.Time в атомную в Go? - PullRequest
0 голосов
/ 19 мая 2018

В моем веб-сервисе RESTFUL, который является онлайн-игрой, я храню время начала каждого вопроса в глобальной переменной, такой как: var MyTime time.Time, которую я должен обновлять после каждого уровня игры.Мое приложение распространяется, поэтому я хочу убедиться, что все мои приложения не обновляют его одновременно.Вот почему я решил сделать его атомарным.На самом деле я знаком с пакетом Golang sync/atomic.Я пытался использовать atomic.LoadPointer() метод, но ему нужен конкретный тип аргумента, который не является безопасным.Есть ли другой способ для этого?

Обновление: Хорошо, я решил свою проблему следующим образом.Я определил переменную времени как atomic.Value и использовал атомарные методы Load и Store.Это код: var myTime atomic.Value myTime.Store(newTime) и load myTime.Load().(time.Time).

Учтите, что метод Load () возвращает интерфейс, поэтому вам нужно написать (time.Time) в конце, чтобы преобразовать его в time.Timeтипа.

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Вы можете оставить время Unix https://golang.org/pkg/time/#example_Time_Unix как атомное, что является int64.Затем преобразуйте время перехода после прочтения атомарного значения.

0 голосов
/ 19 мая 2018

Это невозможно сделать как таковое, потому что time.Time является составным типом:

type Time struct {
    // wall and ext encode the wall time seconds, wall time nanoseconds,
    // and optional monotonic clock reading in nanoseconds.
    //
    // From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),
    // a 33-bit seconds field, and a 30-bit wall time nanoseconds field.
    // The nanoseconds field is in the range [0, 999999999].
    // If the hasMonotonic bit is 0, then the 33-bit field must be zero
    // and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.
    // If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit
    // unsigned wall seconds since Jan 1 year 1885, and ext holds a
    // signed 64-bit monotonic clock reading, nanoseconds since process start.
    wall uint64
    ext  int64

    // loc specifies the Location that should be used to
    // determine the minute, hour, month, day, and year
    // that correspond to this Time.
    // The nil location means UTC.
    // All UTC times are represented with loc==nil, never loc==&utcLoc.
    loc *Location
}

Однако вы можете сделать это с помощью указателей, поэтому *time.Timeбыло бы возможно, если это соответствует вашим потребностям.Но, конечно, это не рекомендуется, поскольку atomic.LoadPointer и atomic.StorePointer используют пакет unsafe для выполнения своей магии.

Намного лучший подход, если он будет работать для вас,это просто использовать мьютекс для защиты вашей ценности.Есть много способов сделать это, но один минимальный пример:

type MyTime struct {
    t  time.Time
    mu sync.RWMutex
}

func (t *MyTime) Time() time.Time {
    t.mu.RLock()
    defer t.mu.RUnlock()
    return t.t
}

func (t *MyTime) SetTime(tm time.Time) {
    t.mu.Lock()
    defer t.mu.Unlock()
    t.t = tm
}
...