Yeah, thanks for that Konstantin. I have done something fairly similar, although all my objects support a Destroyable interface with one method Destroy(). However, I think your idea to closely mimic the defer list and simply push functions is much cleaner. The basic concept seems to work quite well so far and makes the wrapped functions pretty tidy at the expense of some efficiency I imagine. Ive also added a finalizer to the Stack so that in the (hopefully rare) case where the defer might be accidentally omitted, there is potentially a second chance to clean up.
On Thursday, October 20, 2016 at 3:46:00 PM UTC+1, Konstantin Khomoutov wrote: > > On Wed, 19 Oct 2016 15:35:40 -0700 (PDT) > andrew...@miracl.com <javascript:> wrote: > > [...] > > Im considering a scheme where I push every CString onto an > > implementation of a stack, and then call defer once. Im sure some > > people might think it overkill... Kinda like this : > > > > func Outer(arg1 string, arg2 string, arg3 string, arg4 string) Return > > { stack := NewStack() > > defer stack.Destroy() > > return wrapReturn( > > C.inner( > > NewStackCString(arg1, stack).p, > > NewStackCString(arg2, stack).p, > > NewStackCString(arg3, stack).p, > > NewStackCString(arg4, stack).p)) > > } > [...] > > I think something like this should work in Go almost unmodified -- > just you won't have a system-provided "defer list", will have a single > deferred execution of stack.Destroy() and have your own implementation > of that stack type. > > Something like this: > > ----------------8<---------------- > package main > > import "fmt" > > type dtor func() > > type cleanup struct { > dts []dtor > } > > func (c *cleanup) Add(d dtor) { > c.dts = append(c.dts, d) > } > > func (c *cleanup) Cleanup() { > for _, f := range c.dts { > f() > } > } > > type Foo struct{} > > func (f Foo) Close() { > fmt.Println("Foo.Close()") > } > > type Bar struct{} > > func (b Bar) CFree() { > fmt.Println("Bar.CFree()") > } > > func foo() { > var dts cleanup > defer dts.Cleanup() > > foo := Foo{} > dts.Add(foo.Close) > > bar := Bar{} > dts.Add(bar.CFree) > } > > func main() { > foo() > } > ----------------8<---------------- > > (Playground link: https://play.golang.org/p/TqCfBfZb_X). > > > BTW I found myself doing something much like this in some of my C# > projects to avoid nesting hell of > > using (...acquire resource...) { > using (...acquire resource...) { > ...etc ad nauseum > } > > whereas you have a stack-like data type which implements IDisposable, > and you just have a single using() { ... } block for it inside which > you add particular resources to be destroyed to that instance, and at > the end of the block it's told to destroy itself and then it destroys > whatever resources have been added to it. > -- 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.