Go: Defer Blocks (idea)

This is an idea that I’ve had for a while. It’s an extension of defer that behaves similar to handle. I’m not sure if it’s original, but I thought it was worth writing down.

Syntax

defer {
    // Code runs at function exit
}

defer (_ string, err error) {
    if err != nil {
        return "", fmt.Errorf("wrapped: %w", err)
    }
}

Semantics

Example

func CopyFile(dst, src string) error {
	defer (err error) {
		if err != nil {
			return fmt.Errorf("failed to copy %s to %w: %w", src, dst, err)
		}
	}
    in, err  := os.Open(src)
    if err != nil {
	    return err
    }
    defer in.Close()
    out, err := try os.Create(dst)
    if err != nil {
	    return err
    }
	defer (err error) {
		if err != nil {
			_ = os.Remove(dst)
		}
	}
    if _, err := io.Copy(out, in); err != nil {
	    return err
    }
	return out.Close()
}