Go error:gob:type sync.Mutex没有导出的字段

时间:2018-05-30 02:31:44

标签: go mutex gob

我遇到一个问题,如果导出sync.Mutex,我无法将结构保存为gob。如果我使互斥锁未被导出(通过不将其大写),一切似乎都有效。我很想知道为什么会这样,并且确保没有其他问题可以使用未被移植的sync.RWMutex

我发现Google上有几个针对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) } 的相关问题的点击,但没有一个真正解释为什么会发生这种情况。

{{1}}

输出:

  

错误:gob:type sync.Mutex没有导出的字段

1 个答案:

答案 0 :(得分:0)

Gob编码

  

如果我不导出互斥锁(不使用大写字母),那么一切似乎都可以正常工作。我很好奇这是为什么。

Cerise mentioned一样,有一个open issue,但是简而言之,如果您尝试对没有导出字段的结构(例如互斥锁)进行编码,通常会导致编程错误。

不过,有一些方法可以解决此特定问题。

您可以将互斥锁设为私有,并将锁定/解锁包装在公共函数中,而不是进入用于操作互斥锁的结构。例如

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进行咬刺没有其他问题。

Mutexes与Go运行时的进程内内存和调度程序紧密耦合。它们帮助Go​​运行时确定允许哪些goroutine读取或写入内存的特定部分,并帮助您确定何时计划安排这些goroutine(即,等待互斥体解锁的goroutine直到互斥体解锁后才会进行调度)

如果使用Gob将数据结构复制到另一个进程,则与发送gob的进程相比,接收方进程的运行时内部状态完全不同,因此互斥体无法进行逻辑传输。将互斥锁复制到另一个过程就像在火星上使用Earth GPS坐标一样。他们只是不匹配。

  

当我从料滴读回Dog对象时,无论将互斥量保存到料滴中时,无论该互斥量处于何种状态,该互斥量都似乎已解锁。我可以指望这种行为吗?

正如documentation for Mutex所述,“互斥锁的零值是未锁定的互斥锁。”是的,您可以依靠这种行为。

其他编码器

我认为,尽管gob出现在stdlib中,但它并没有引起太多关注,因为还有许多其他成熟的编码选项可用。如果gob不能满足您的需求,则可以使用许多其他选项-JSON,Cap'n Proto,net / rpc等,它们具有不同的特征,可能会更适合您。