如果结构具有导出的sync.Mutex,则无法将其保存为gob,这是我遇到的问题。如果我使互斥不可导出(通过不大写它),一切似乎都能正常工作。我很想了解为什么会出现这种情况,并确保不存在其他问题,因为它是一个未导出的sync.Mutex。
我看到谷歌上有几个关于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没有导出字段
发布于 2019-05-21 19:50:57
Gob编码
如果我使互斥不可导出(通过不大写它),一切似乎都能正常工作。我很想知道这是为什么。
作为塞里西,这里有一个公开发行,但简而言之,如果您试图对没有导出字段的结构(例如互斥)进行编码,通常是一个编程错误。
不过,有一些方法可以解决这个特殊的问题。
您可以将互斥锁设置为私有,并将锁/解锁包装在一个公共函数中,而不是深入到结构中来操作互斥锁。例如。
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,但通常这似乎是一项相当多的工作。
一般穆特克斯
...and确保未导出的sync.Mutex没有其他问题。
Mutexe与Go运行时的进程内存和调度程序紧密耦合。它们帮助Go运行时决定允许哪些goroutines读取或写入特定的内存部分,并决定何时可以调度这些goroutines (例如,等待互斥锁解锁的大猩猩将在未锁定互斥锁之前不会被调度)。
如果使用gob将数据结构复制到另一个进程,则收件人进程的运行时与发送Gob的进程具有完全不同的内部状态,因此不能逻辑地传输互斥对象。将互斥体复制到另一个进程有点像在火星上使用地球GPS坐标。他们只是不相配。
当我从一个gob中读取一个Dog对象时,它看起来就像一个互斥对象被保存到一个gob时,不管它的状态如何,它都是解锁的。这是我可以信赖的行为吗?
正如Mutex文档声明的那样,“Mutex的零值是一个未锁定的互斥体。”所以是的,你可以依靠这种行为。
其他编码器
在我看来,尽管gob存在于stdlib中,但它并没有得到太多的关注,因为还有许多其他成熟的编码选项可用。如果gob不能满足您的需要,那么还有许多其他选项可用-- JSON、Cap、net/rpc等,它们的不同特性可能更适合您。
https://stackoverflow.com/questions/50595570
复制相似问题