google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library

Home Page:https://flatbuffers.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problem with default values in Go library

estromenko opened this issue · comments

Mutation methods in Go library do not apply if default value is set. There was the same issue in C++ library, but it looks line it is not still fixed in Go. I use go1.17 and the latest flatbuffers.

Here is some examples:

image

image

image

Flatbuffers has an optimization where if the default value is set, we skip writing the value in the binary. This also means it cannot be mutated, since mutation works by modifying an existing value in place and you can't do that if it's simply not there.

If you require mutation, I suggest making the default some sentinel value, e.g. -1, and always initialize this inside your application. You could also rebuild the flatbuffer if the code isn't performance sensitive.

If you weren't using Go, #6014 allows you to use hp: short = null to avoid the sentinel, but it would make all the types optional and you'd still have to initialize the value in your application before building the flatbuffer to use the mutation api.

My problem was solved by removing default value from schema. I think, this behaviour is not explicit. In such cases it is required to define default values outside of schema.
Maybe, I am not right, but for me it looks like a bug

My problem was solved by removing default value from schema.

Cool, resolving. Note that removing the default value from the schema makes the default value implicitly zero, so if you fail to initialize hp, or initialize it to zero, the value won't be written and mutation will fail.

I think, this behaviour is not explicit. In such cases it is required to define default values outside of schema.
Maybe, I am not right, but for me it looks like a bug

I agree that this behavior is mysterious/complex but its the result of organic evolution and our commitment to not having breaking changes in the binary format or schema language. The in-place mutation API came after the default-elision thing.

For what its worth the tutorial does advise on this in the mutation API section

Note that any mutate functions on a table will return a boolean, which is false if the field we're trying to set is not present in the buffer. Fields are not present if they weren't set, or even if they happen to be equal to the default value. For example, in the creation code above, the mana field is equal to 150, which is the default value, so it was never stored in the buffer. Trying to call the corresponding mutate method for mana on such data will return false, and the value won't actually be modified!

One way to solve this is to call ForceDefaults on a FlatBufferBuilder to force all fields you set to actually be written. This, of course, increases the size of the buffer somewhat, but this may be acceptable for a mutable buffer.