-
Notifications
You must be signed in to change notification settings - Fork 1
Generate non-pointer-laden Go types? #1
Comments
Hmm, maybe the best of both worlds would be generating different code if CUE's default is the Go zero value |
Also, non-pointer types would be much better for the read-time cases, and probably wouldn't have such issues with existence/default ambiguity so long as they don't need to be re-marshaled |
This is one of the most annoying aspects of go for me. Not sure what the best answer is but I would be very hesitant to lose the ability to disambiguate between "not specified" and "set to zero value" |
Yeah, i quite agree. That's why i ultimately took the pointerful route for initial Go codegen. i think i may have the pieces of at least a partial solution to it with Thema, but i don't yet see how they fit together into a pattern that i feel is simple enough for everyday use. Specifically, i have two pieces:
The generic initializer doesn't solve the ambiguity problem in non-pointer types. Nothing can. Still, i have the nagging feeling that there's something just outside my field of view that, combined with these two pieces, lets us significantly relieve the tension between DX and ambiguity. |
Right now, the generated Go types represent optionality in the schema using pointers. So, if we have a CUE/thema schema like this:
We'd get the corresponding Go struct:
This isn't great. It means the most convenient way of writing an
Obj
instance is:This is awkward. Generics makes this easier, but it's still pretty poor DX compared to just good ol' fashioned struct declarations.
Unfortunately, a nil pointer is the only mechanism Go's type system has for expressing the absence of a field/var. The presence of
omitempty
doesn't help us - that conflates existence with defaultness, which are things that CUE clearly delineates between. Go, OTOH, just has anemic zero values for defaults.This results in a pile of ambiguities. With
string
, we can't tell if the user wants""
, or simply didn't specify a value for the field:field
in encoded JSON, all we know for sure is thatomitempty
was declared onObj
. The user may or may not have wanted""
as the value"foo"
."field": ""
, all we know for sure is thatomitempty
wasn't onObj
; we don't know if the user wanted""
(in which case a default should not be applied) or simply declared nothing (in which case it should, but CUE can't do it anyway because it can't override the value).These limitations apply whether in the encoded JSON or directly in Go (the former arises from the latter). https://go.dev/play/p/WbDTMNJ_hdx illustrates how only the presence of
*string
lets us disambiguate.Still, i wonder if, perhaps in the limited context of use by a builder, we might generate types that don't have all the pointers, just for the sake of DX. Gonna keep this issue open as a reference/to ruminate.
The text was updated successfully, but these errors were encountered: