goinlineprogram-flow

Deferring deferrements in Golang


I'm new to Go and I have to write an app which has to open lots of files at various points. The code to open each file would be

fl, err := os.Open(..)
check(err)
defer fl.Close()

where check simply calls panic if anything goes wrong.

Now, as I said, that snippet repeats itself quite a few times. I'd like to have something like this:

func foo(f string){
    fl, err := os.Open(f)
    check(err)
    defer fl.Close() //lolwut
}

Of course once foo returns, defer would kick in and close the file.

Is there a way to defer deferrements for a function until its caller decides it's time?

What I've tried to do so far is, put the defer in an anonymous function, have foo return it and have the caller execute that (preferably in a one-liner). Yet I'm hitting some obstacles implementing that and I'm not even sure if it's the correct approach.

tl;dr: Is there a way to defer deferrements to the calling function in Go?


Solution

  • I think you make a mistake in your design. What you wanted to do originally doesn't really make sense: If you wanted to defer Close() into the caller, you take away all the flexibility to decide on deallocation from the caller. What if the caller has to keep around the file for longer than its own duration?

    You might want to think of foo() as a ressource-allocating function, just like io.Open() is. Thus, if a function calls foo(), it has just allocated a resource. foo() is not responsible for deallocating this resource, the caller is, just like in the case of io.Open().