On 14 March 2018 at 01:22, Maverick Woo <maverick....@gmail.com> wrote: > Having said the above, in your example, you have a (morally) `shape.Print` > function that takes an interface value of the intended "descendants" and you > expose their fields using interface methods. This is all very idiomatic---no > doubt. However, if there are 50 "base" fields similar to shape.name, then a > straightforward extension is to have each of the descendants implement 50 > methods to expose the fields. Of course, in this case we may introduce an > interface method that returns a struct of these base fields. An alternative > but hopefully still idiomatic solution would be to bring back struct > embedding and turn `shape.Print` into a method that receives the base > struct, and now the base fields in a descendant can be accessed through the > receiver.
Struct embedding is just fine - the problem is with having Print as a method *on* the embedded struct that also requires information about the value that it's embedded in. There are (at least) two idiomatic approaches that you can use instead. You can create an embeddable struct that makes it easier for instances of your interface to implement the interface, while keeping the Print functionality as a separate function rather than a method: https://play.golang.org/p/fzqTZRNmvXY Or you could make the information struct itself primary, so that the interface type is only used for the "plugged in" part of the value: https://play.golang.org/p/4KMKbvNto6h Either of these approaches can be appropriate for different problems; which one is right usually depends on how static the outer methods need to be. In many cases, the latter approach is good because you get strong guarantees about the behaviour of the top level methods and the "plugged in" value doesn't have to be responsible for much. But sometimes, it's important to give the value full control over all its methods, and in that case defining an interface type for the whole thing (perhaps with helpers like that ShapeInfo struct) can be the way forward. The different approaches will have different performance characteristics too, which might also influence the decision. Note that both these approaches use embedding, but neither is vulnerable to your original problem, because we're not trying to embed an object in itself. > Finally, may I ask what "go.mod" is? I didn't know I did that. Thanks! Ha, looks like I created it myself. See https://research.swtch.com/vgo. It was nice to use vgo in this case because I could download and run your multipackage demo without putting it in my $GOPATH. Hope this was helpful. cheers, rog. > > Maverick > > > > On Monday, March 12, 2018 at 2:15:56 PM UTC-4, rog wrote: >> >> This is an interesting edge case that you've run across, and I've done >> similar things in the past but I don't buy your motivational example. >> Putting an embedded recursive reference to a value within the value >> itself seems to be asking for trouble to me. >> >> Go emphasises "has-a" relationships over "is-a" relationships, and >> ISTM that you're trying hard for the latter when the former provides a >> straightforward path to doing what you want. >> >> For example: https://play.golang.org/p/b2J05LxzGpT (stripped down to a >> single file so that it works in the Go playground). >> >> Specifically, by changing the Print function to a function from a >> method, we allow it to run on any value that implements the Shape >> interface without being a method on Shape itself. That is, Print *has >> a* Shape, rather than being part of a Shape. >> >> Does that not work for you? >> >> cheers, >> rog. > > -- > 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. > For more options, visit https://groups.google.com/d/optout. -- 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. For more options, visit https://groups.google.com/d/optout.