Go: proposal: Go 2: remove io.Seeker, SeekStart, etc., change Seek method

Created on 12 Jun 2018  路  5Comments  路  Source: golang/go

Copying @bradfitz's comment https://github.com/golang/go/issues/17920#issuecomment-260542015 into a separate proposal.

For Go 2 we should consider changing the Seek method to just take a file position, not a whence argument. We should consider adding SeekFromCurrent and SeekFromEnd, though I suspect they are unnecessary. We should change Seeker similarly. We should remove io.SeekStart, io,SeekCurrent, and io.SeekEnd.

Rationale: the current Seek method is copied from C. It presents three different interfaces, and doesn't make much sense as a single method in Go. People who implement the io.Seeker interface often only implement it for io.SeekStart, and do not correctly handle the other possible values.

See also #17920, which this would replace.

Go2 NeedsDecision Proposal

Most helpful comment

We should consider adding SeekFromCurrent and SeekFromEnd, though I suspect they are unnecessary.

I looked through all my own code and the Go code at my company.

  • Most uses of Seek are indeed SeekStart.
  • We've never used SeekCurrent.
  • There are a handful of uses of SeekEnd. Most of these are in functions which want to take a single io.ReadSeeker and only call Seek(0, io.SeekEnd) once, at the beginning, to learn the file size. (http.ServeContent does this too.) Perhaps this could be changed in Go 2 to use some standard interface for file-like things that know their size.

All 5 comments

We should consider adding SeekFromCurrent and SeekFromEnd, though I suspect they are unnecessary.

I looked through all my own code and the Go code at my company.

  • Most uses of Seek are indeed SeekStart.
  • We've never used SeekCurrent.
  • There are a handful of uses of SeekEnd. Most of these are in functions which want to take a single io.ReadSeeker and only call Seek(0, io.SeekEnd) once, at the beginning, to learn the file size. (http.ServeContent does this too.) Perhaps this could be changed in Go 2 to use some standard interface for file-like things that know their size.

SeekCurrent is generally only used with 0 to learn the current seek position, and often just to restore it at the end of some operation that really wanted an io.ReaderAt and is hoping that restoring it afterwards won't be too racy.

I support the proposal to reduce the Seek method. That would avoid nasty hacks like this.

That said, I wouldn't discount use-cases for SeekEnd and SeekCurrent. If we provide other interfaces that returned the current offset and the total offset more idiomatically, then the equivalent of SeekEnd and SeekCurrent can be implemented by the user with a little bit of math.

Roughly speaking:

f.Seek(n, SeekStart)   => f.Seek(n)
f.Seek(n, SeekCurrent) => f.Seek(f.CurrentOffset()+n)
f.Seek(n, SeekEnd)     => f.Seek(f.EndOffset()+n)

EndOffset is just the filesize and can be named Size or something. It is a common piece of information needed with the ReaderAt interface (see #15822).

I much rather see idiomatic methods to access the current offset and end offset than separate SeekFromCurrent and SeekFromEnd methods.

os.File is an API to the OS. Second-guessing the OS model for that API could have unintended consequences. If you must change os.File.Seek, please

a) rename os.File.Seek to .SeekFrom, and
b) add os.File.SeekTo(n) (or .SeekPos?) as an alias for .SeekFrom(n, io.SeekStart).

For an append-only file with an index at file's end, I use seek-from-end to read the index size, then seek-from-current to read the index. Thanks!

Edit:
@dsnet, wouldn't os.File.CurrentOffset & .Size entail a separate syscall?

hoping that restoring it afterwards won't be too racy.

If the underlying io.Reader is guaranteed to be unique, then code of that form can use a sync.Mutex or similar synchronization to ensure that it won't be racy at all.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jayhuang75 picture jayhuang75  路  3Comments

stub42 picture stub42  路  3Comments

dominikh picture dominikh  路  3Comments

enoodle picture enoodle  路  3Comments

natefinch picture natefinch  路  3Comments