Skip to content

Instantly share code, notes, and snippets.

@abdivasiyev
Created June 16, 2025 09:25
Show Gist options
  • Save abdivasiyev/18a039cd228ec7503849f02b25ccfac1 to your computer and use it in GitHub Desktop.
Save abdivasiyev/18a039cd228ec7503849f02b25ccfac1 to your computer and use it in GitHub Desktop.
Resource management using bracket pattern in Go
// package resource provides bracket pattern for
// resource management
package resource
import (
"fmt"
"mime/multipart"
"net/http"
"os"
)
func With[R any, T any](
acquire func() (R, error),
release func(R) error,
fn func(R) (T, error),
) (T, error) {
var zero T
r, err := acquire()
if err != nil {
return zero, fmt.Errorf("failed to acquire resource: %w", err)
}
result, err := fn(r)
if err != nil {
releaseErr := release(r)
if releaseErr != nil {
return zero, fmt.Errorf("failed to process resource: %w: failed to release resource: %w", err, releaseErr)
}
return zero, fmt.Errorf("failed to process resource: %w", err)
}
releaseErr := release(r)
if releaseErr != nil {
return zero, fmt.Errorf("failed to release resource: %w", releaseErr)
}
return result, nil
}
func WithFile[T any](path string, fn func(*os.File) (T, error)) (T, error) {
acquire := func() (*os.File, error) { return os.Open(path) }
release := func(f *os.File) error { return f.Close() }
return With(acquire, release, fn)
}
func WithMultipartFile[T any](
r *http.Request,
key string,
fn func(multipart.File) (T, error),
) (T, error) {
acquire := func() (multipart.File, error) {
f, _, err := r.FormFile(key)
return f, err
}
release := func(f multipart.File) error { return f.Close() }
return With(acquire, release, fn)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment