On Wed, Dec 7, 2022 at 4:39 AM Brian Candler <b.cand...@pobox.com> wrote:
> On Tuesday, 6 December 2022 at 21:05:48 UTC dple...@google.com wrote: > >> I am trying to figure out if there's a good way to build a helper that >> can be used against different sets of nested types that have a common >> structure. >> >> So, for example, say there are two libraries, `lib1` and `lib2` and both >> define types Foo, Bar, and Baz with: >> >> type Foo struct { ... } >> type Bar struct { ... } >> func (b *Bar) GetFoo() *Foo { ... } >> type Baz struct { ... } >> func (b *Baz) GetBar() *Bar { ... } >> >> But `lib1` and `lib2` both define different additional methods on some of >> these structs, so I can't just merge them into a single library. >> > > It seems to me that lib1.{Foo,Bar,Baz} and lib2.{Foo,Bar,Baz} are > completely different types. They just happen to have similar names. > > Hence I ask, what's the commonality that you're trying to expose? If it's > that both lib1.Baz and lib2.Baz have a GetBar() method, then that sounds > like an interface - except if one returns a lib1.Bar and the other returns > a lib2.Bar, then they are not the same interface at all, so you're back to > "these are completely different types". Is there something common in Foo ? > <snip> Why not just have HelperFn1(lib1.Baz) and HelperFn2(lib2.Baz)? > My actual use case involves a code generator, where lib1 and lib2 (and possibly dozens of additional libraries) are all outputs of the same generator with slightly different arguments, generated by various different teams and therefore entirely outside of my control. The generator in question reads a schema file and outputs a library of Go structs for all the data types defined by the schema. There are more than a thousand such data types; they have getters and setters for their attributes, and they're all nested in a giant tree, so e.g. code could call root := &lib1.Root{} root.GetFoo().GetBar().GetBaz().GetQux().GetFleem().SetName("hello") The problem is that various users of the code generator have their own schemas, which are generally made by taking a common standard schema and adding extra fields needed by whatever specific project the users are working on. So for example one project might add a .GetSpoo() method to the Foo type, while another adds GetAlias to Fleem, etc. What I really want to do is be able to write a helper like: package examplehelper func SetFleemName(root ???, name string) { root.GetFoo().GetBar().GetBaz().GetQux().GetFleem().SetName(name) } such that any project can have its own generated library and can call `examplehelper.SetFleemName(root, "foo")` on a Root{} from their own generated library, as long as the Root has GetFoo(), the Foo has GetBar(), etc. down to the Fleem having a SetName(string). This is technically possible with generics, but not practical, because it requires writing e.g.: x := lib1.Root{} helper.SetFleemName[*lib1.Fleem, *lib1.Qux, *lib1.Baz, *lib1.Bar, *lib1.Foo](x, "foo") and in my real use case that list of type parameters would have more than a thousand types in it. Right now I'm experimenting with whether it's reasonable to use code generation to solve this - a code generator could either just copy a helper library and replace all the imports with a specific generated library, or could build a generated-library-specific "bridge" library that defines a bunch of var SetFleemName = generichelper.SetFleemName[*lib1.Fleem, *lib1.Qux, ...<a thousand more types>] But there's a lot of overhead to having everything go through a generator, and it makes the code harder to read, harder to debug, and harder to use in IDEs. I am hoping that there's some Golang feature I'm just not aware of that would allow me to do this in the language itself, but I haven't been able to find one so far. Thanks, Dan -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAAViQtgco5qCX%3DLrTcaJ0q2VnuixwYBk-KcCuyoO5XPPSMpufQ%40mail.gmail.com.