I am saving go structs in mongo using mgo. I wish to save them with a hash of that struct (and a secret) to determine whether they have been tampered with (and I do not wish the mongo db itself to have the secret).
Currently I am hashing the structs by serializing them using gob
whose ordering of struct components is well-defined. This works great, save when I go to reread the struct from mango, things have changed - to be precise the time values in mongo have truncated accuracy compared to go - therefore the hashes do not match up.
My planned work around for this is simply to marshall and unmarshall the struct from BSON before calculating the hash, i.e.:
[]byte
Now, that's more than a little circuitous.
If I could guaranteed that the BSON itself always preserved order of components in structs, I could:
byte[]
Which would be less nasty (albeit that it would still require converting to BSON twice).
Any ideas?
Answering your actual question, yes, you can trust mgo/bson
to always marshal struct fields in the order they are observed in the code. Although not yet documented (issue), this is very much intentional behavior, and even mgo itself depends on it internally.
Now, responding to your intended usage: don't do that. The fact fields are in a guaranteed order does not mean the binary format is stable as a whole. Even now there are known ways the output can change without breaking even the existing clients, but that would break a hash of its output.
Here is some suggested reading to understand a bit better the ins and outs of the problem you are trying to solve (I'm the author):
This is precisely addressing the issue of marshaling an arbitrary or map with arbitrary fields and keys in a stable way, to obtain a stable hash out of it for signatures. The reference implementation is in Go.