go proposal: io/v2: remove io.Seeker, SeekStart, etc., change Seek method

e4eetjau  于 2个月前  发布在  Go
关注(0)|答案(5)|浏览(33)

将@bradfitz的评论#17920(评论)复制到一个单独的提案中。
对于Go 2,我们应该考虑将Seek方法更改为仅接受文件位置,而不是whence参数。我们应该考虑添加SeekFromCurrentSeekFromEnd,尽管我怀疑它们可能是不必要的。我们应该类似地更改Seeker。我们应该删除io.SeekStartio,SeekCurrentio.SeekEnd
理由:当前的Seek方法是从C复制过来的。它提供了三种不同的接口,作为Go中的单个方法没有太大意义。实现io.Seeker接口的人通常只为io.SeekStart实现它,并且没有正确处理其他可能的值。
另请参阅#17920,这将被替换。

woobm2wo

woobm2wo1#

我们应该考虑添加 SeekFromCurrentSeekFromEnd,尽管我怀疑它们是不必要的。
我查看了我自己的代码和我公司的 Go 代码。

  • Seek 的大多数用途确实是 SeekStart。
  • 我们从未使用 SeekCurrent。
  • 有少数 SeekEnd 的使用场景。其中大部分出现在希望只调用一次 Seek(0, io.SeekEnd)的函数中,以了解文件大小。(http.ServeContent 也这样做。)也许在 Go 2 中可以改变这一点,使用某种标准接口来表示类似文件的对象,这些对象知道它们的大小。
efzxgjgh

efzxgjgh2#

SeekCurrent通常仅与0一起使用,以学习当前的寻道位置,并且通常仅在某些操作结束时恢复它,这些操作确实需要一个io.ReaderAt,并希望在此之后恢复它不会过于抢手

mbskvtky

mbskvtky3#

我支持减少 Seek 方法的提议。这样可以避免像这样的恶意攻击。
然而,我不排除使用 SeekEndSeekCurrent 的情况。如果我们提供其他接口,更符合习惯地返回当前偏移量和总偏移量,那么用户可以通过一些数学计算实现等效于 SeekEndSeekCurrent 的方法。
大致来说:

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 只是文件大小,可以命名为 Size 或其他名称。这是与 ReaderAt 接口(参见 #15822)一起需要的常见信息。
我更希望看到访问当前偏移量和结束偏移量的惯用方法,而不是单独的 SeekFromCurrentSeekFromEnd 方法。

rqqzpn5f

rqqzpn5f4#

os.File 是操作系统的API。对这个API的OS模型进行二阶猜测可能会产生意想不到的后果。如果你必须修改os.File.Seek,请
a) 将os.File.Seek重命名为 .SeekFrom,并
b) 为 .SeekFrom(n, io.SeekStart) 添加 os.File.SeekTo(n)(或 .SeekPos?) 作为别名。
对于一个在文件末尾有索引的只追加文件,我使用从末尾开始寻找来读取索引大小,然后使用从当前位置开始寻找来读取索引。谢谢!
编辑:
@dsnet,os.File.CurrentOffset & .Size 是否会涉及单独的系统调用?

9avjhtql

9avjhtql5#

希望稍后恢复它不会是 too 的竞争。
如果底层的 io.Reader 保证是唯一的,那么这种形式的代码可以使用一个 sync.Mutex 或类似的同步来确保它根本不会发生竞争。

相关问题