IMO going back to return statements for error detection is to throw away years of advancement. The problem with what you're describing is now every call has to be tested for errors because only the call-site has a chance to do this.
Contrast this with exceptions: if I don't know what to do with a failure at this level then I just ignore it. Some caller higher up the chain will know and can handle it.
Your examples seem overly trivial. In real code it would be very rare for the level of code that's actually opening files (something far down in the libraries) to also be handling exceptions.
Go actually does provide a mechanism similar to exceptions. The functionality is provided by the functions panic, defer, and recover. Idiomatic Go does not like panics (i.e. exceptions) to escape API boundaries, but otherwise you are just as free to use them as any language providing exceptions.
Years of advancement or years of wandering aimlessly? It depends on the coders, of course. More often than not I've seen exceptions used for non-exceptional errors: normal errors best handled immediately by the code that triggered it. The use of exceptions there needlessly defers dealing with the error, passing it up the call chain to code that shouldn't know particulars.
Making both returned errors and exceptions available at least offers the opportunity to use the better tool for the circumstances. Both are very valuable and clear under different circumstances.
Contrast this with exceptions: if I don't know what to do with a failure at this level then I just ignore it. Some caller higher up the chain will know and can handle it.
Your examples seem overly trivial. In real code it would be very rare for the level of code that's actually opening files (something far down in the libraries) to also be handling exceptions.