Defer to outside a function

Issue

A common pattern I use is:

resource.open()
defer resource.close()

sometimes checking errors in between, which leads to:

err := resource.open()
if err != nil{
     //do error stuff and return
}
defer resource.close()

Sometimes I will need multiple open/close resources in a row, leading to a variation of the previous 5 lines to be repeated one after another. This variation may be repeated verbatim several times in my code (where I need all the same resources).

It would be wonderful to wrap all this in a function. However doing so would close the resource as soon as the function call is over. Is there any way around this – either deferring to a "level up" the call stack or some other way?

Solution

One way to do this is using an "initializer" function with callback:

func WithResources(f func(Resource1, Resource2)) {
   r1:=NewResource1()
   defer r1.Close()
   r2:=NewResource2()
   defer r2.Close()
   f(r1,r2)
}

func F() {
  WithResources(func(r1 Resource1, r2 Resource2) {
    // Use r1, r2
  })
}

The signature of the function f depends on your exact use case.

Another way is to use a struct for a resource set:

type Resources struct {
   R1 Resource1
   R2 Resource2
   ...
}

func NewResources() *Resources {
   r:=&Resources{}
   r.R1=NewR1()
   r.R2=NewR2()
   return r
}

func (r *Resources) Close() {
   r.R1.Close()
   r.R2.Close()
}

func f() {
   r:=NewResources()
   defer r.Close()
   ...
}

Answered By – Burak Serdar

Answer Checked By – Clifford M. (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.