Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go optional scalars #7104

Merged
merged 6 commits into from
Feb 16, 2022
Merged

Go optional scalars #7104

merged 6 commits into from
Feb 16, 2022

Conversation

chriscraws
Copy link
Contributor

Hi, I'm taking a first pass at adding support for optional scalars to Go.

#6471
#6014

I haven't authored tests yet, but will do so if this approach seems reasonable!

Essentially the changes are the following:

  • Non-optional types are now always written
  • Optional scalars are generated as *type instead of type for the object-api and the normal functional API.
  • Mutators for optional scalars are the same as they were before, and just return false if the field is not present (they don't accept a pointer)

Example getter:

func (rcv *ScalarStuff) MaybeI8() *int8 {
	o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
	if o != 0 {
		return rcv._tab.GetInt8(o + rcv._tab.Pos)
	}
	return nil
}

Example setter

func ScalarStuffAddMaybeI8(builder *flatbuffers.Builder, maybeI8 *int8) {
	if maybeI8 != nil {
		builder.PrependInt8(*maybeI8)
		builder.Slot(1)
	}
}

Example setter for non-optional type:

func ScalarStuffAddDefaultF64(builder *flatbuffers.Builder, defaultF64 float64) {
	builder.PrependFloat64(defaultF64)
	builder.Slot(29)
}

@github-actions github-actions bot added c++ codegen Involving generating code from schema golang labels Feb 14, 2022
@CasperN
Copy link
Collaborator

CasperN commented Feb 14, 2022

Can you generate code for optional_scalars.fbs?

@chriscraws
Copy link
Contributor Author

Done - not sure why I left that out of the commit

@CasperN
Copy link
Collaborator

CasperN commented Feb 14, 2022

I'm not a Go person, but the generated code generally looks good to me

Non-optional types are now always written

This doesn't align with the other languages. We don't put scalars in the binary if the user doesn't set the field.
Even if they do set the field, if they set it to the default value, we don't put it in the binary, unless
the user opt-ed into 'force defaults' (which is default off)

@chriscraws
Copy link
Contributor Author

Non-optional types are now always written

This doesn't align with the other languages. We don't put scalars in the binary if the user doesn't set the field. Even if they do set the field, if they set it to the default value, we don't put it in the binary, unless the user opt-ed into 'force defaults' (which is default off)

That mainly only applies for the object-api - all fields still need explicit encoding using the imperative API, but with this change values are stored regardless of whether they are the default. That's what I interpreted from these statements from the feature proposal:

Instead of omitting zero-like values, the generated code must store them.
It aligns with the "force_defaults" + "IsFieldPresent" hacky manual approximation of this feature.

Sounds like I've misinterpreted though, so to be clear - the recommended approach is to leave 'non-optional' fields as-is (store only when the value is not the default or the implicit zero-default) and for fields that must always be written but may take any value, they need to be marked null in the schema, and I'll need to specify defaults in my code, migrating scalar fields to be optional instead.

@CasperN
Copy link
Collaborator

CasperN commented Feb 15, 2022

the recommended approach is to leave 'non-optional' fields as-is (store only when the value is not the default or the implicit zero-default)

Yes, that is correct.

and for fields that must always be written but may take any value, they need to be marked null in the schema, and I'll need to specify defaults in my code, migrating scalar fields to be optional instead.

Yep, that's the best way.


Instead of omitting zero-like values, the generated code must store them.

It aligns with the "force_defaults" + "IsFieldPresent" hacky manual approximation of this feature.

Yeah that I meant was:

  • in the schema table Foo { a: int = null } calling FooAddA(b, 0) will store the zero in the binary.
    This is unlike calling BarAddA(b, 0) for table Bar { a: int }, which would not store anything.

  • Some users who cared about the distinction between "A=0 in the binary" and "A is not in the binary" would use ForceDefaults and an IsFieldPresent to detect whether BarAddA(b, 0) was called. This was generally considered to be suboptimal

@chriscraws
Copy link
Contributor Author

I see! Makes sense, thanks for the clarification - I'll update this PR to have the normal behavior for scalars and will add tests.

@chriscraws
Copy link
Contributor Author

Thanks for looking at this - I've added tests

@CasperN
Copy link
Collaborator

CasperN commented Feb 15, 2022

tests LGTM

Pinging @rw, who started the go stuff

@CasperN
Copy link
Collaborator

CasperN commented Feb 16, 2022

@dbaileychess were you working on windows CI recently? FYI they seem to be broken, unrelated to this PR

@dbaileychess
Copy link
Collaborator

Hmm, nothing that extreme. Some dependency in our CI must have changed. Let me take a look.

@dbaileychess
Copy link
Collaborator

Attempting fix of CI in #7105

@dbaileychess
Copy link
Collaborator

Seems to be fixed. I restarted the checks here.

@dbaileychess
Copy link
Collaborator

Hmm, maybe a force push is required, It is still using the old CI workflow.

@CasperN
Copy link
Collaborator

CasperN commented Feb 16, 2022

Ok, seems all checks pass and the code LGTM (with the caveat that I'm not a Go person). @chriscraws, are we good to merge?

@chriscraws
Copy link
Contributor Author

SGTM, thanks for reviewing

@CasperN CasperN merged commit 06f4af1 into google:master Feb 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ codegen Involving generating code from schema golang
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants