Ошибка Go: gob: тип sync.Mutex не имеет экспортируемых полей - PullRequest
0 голосов
/ 30 мая 2018

У меня возникла проблема, из-за которой я не могу сохранить структуру как гоб, если она экспортирована sync.Mutex.Кажется, все работает, если я сделаю мьютекс неэкспортированным (не используя его заглавные буквы).Мне любопытно понять, почему это так, и убедиться, что нет другой проблемы с поглощением неэкспортированного sync.Mutex.

. Я вижу, что в Google есть несколько обращений для связанной проблемы с sync.RWMutex, ноникто не объясняет, почему это происходит.

package main

import (
    "sync"
    "encoding/gob"
    "os"
    "fmt"
)

func writeGob(filePath string, object interface{}) error {
    file, err := os.Create(filePath)
    defer file.Close()

    if err != nil {
        return err
    }

    encoder := gob.NewEncoder(file)
    err = encoder.Encode(object)
    return err
}

type Dog struct {
    Name string
    GobMux sync.Mutex
}

func main() {
    d := &Dog{Name: "Fido"}
    err := writeGob("./gob", d)
    fmt.Printf("Error: %v\n", err)
}

Вывод:

Ошибка: gob: тип sync.Mutex не имеет экспортируемых полей

1 Ответ

0 голосов
/ 21 мая 2019

Кодировка Gob

Кажется, все работает, если я сделаю мьютекс неэкспортированным (не используя его заглавные буквы).Мне любопытно понять, почему это так.

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

Однако есть несколько способов обойти эту конкретную проблему.

Вы можете создать мьютексprivate и обернуть блокировку / разблокировку в публичной функции, вместо того, чтобы проникнуть в структуру для манипулирования мьютексом.Например,

func (d *Dog) SetName(name string) {
    d.GobMux.Lock()
    d.Name = name
    d.GobMux.Unlock()
}

Вы также можете обернуть тип и вытащить мьютекс:

type Dog struct {
    Name string
}

type DogWrapper struct {
    Dog *Dog
    GobMux sync.Mutex
}

Это довольно громоздко, если у вас много небольших структур, но для меньшего числа более сложных структур.все может быть в порядке.

Наконец, «правильный» способ решить эту проблему - написать собственные подпрограммы GobEncode / Decode.В stdlib есть несколько редких примеров, таких как time.GobEncode, но в целом это выглядит довольно трудоемко.

Мьютексы в целом

... и убедитесь, чточто нет никакой другой проблемы с поглощением неисследованного sync.Mutex.

Мьютексы тесно связаны с оперативной памятью и планировщиком среды выполнения Go.Они помогают среде выполнения Go определять, какие подпрограммы разрешено читать или записывать в определенную часть памяти, а также решать, когда эти распрограммы могут быть запланированы (т. Е. Подпрограмма, ожидающая разблокировки мьютекса, не будет запланирована, пока мьютекс не будет разблокирован)..

Если вы используете Gob для копирования структуры данных в другой процесс, среда выполнения процесса получателя имеет совершенно другое внутреннее состояние по сравнению с процессом, отправляющим гоб, и поэтому мьютекс не может быть логически перенесен.Копирование мьютекса в другой процесс было бы похоже на использование GPS-координат Земли на Марсе.Они просто не совпадают.

, когда я читаю объект Dog из гоба, похоже, что мьютекс разблокирован независимо от состояния мьютекса, когда он был сохранен в гобе.На это поведение я могу рассчитывать?

Как указано в документации для Mutex , «нулевое значение для Mutex - это разблокированный мьютекс».Так что да, вы можете положиться на это поведение.

Другие кодеры

По моему мнению, несмотря на присутствие гоба в stdlib, ему не уделяется много внимания, потому что есть много других доступных вариантов кодирования.,Если gob не соответствует вашим потребностям, есть много других доступных вариантов - JSON, Cap'n Proto, net / rpc и т. Д. С различными характеристиками, которые могут работать лучше для вас.

...