Go语言中Seeker接口的用法详解

 更新时间:2024年10月10日 09:21:33   作者:景天科技苑  
Go语言标准库中的io包提供了一系列接口,用于处理各种I/O操作,其中Seeker接口在处理大文件或需要随机访问的场景中非常有用,本文将结合具体案例,详细介绍Go语言中io包的Seeker接口的用法,需要的朋友可以参考下

Seeker接口

在现代软件开发中,高效的输入输出(I/O)操作是提高程序性能的关键之一。特别是在处理大量数据时,I/O操作的效率直接影响到应用程序的响应速度和用户体验。Go语言标准库中的io包提供了一系列接口,用于处理各种I/O操作,其中Seeker接口在处理大文件或需要随机访问的场景中非常有用。本文将结合具体案例,详细介绍Go语言中io包的Seeker接口的用法。

一、Seeker接口简介

设置光标的位置,通过设置的光标位置来读写文件
用于在数据流中将光标跳转到指定的位置

Seeker接口表示一个定位器,可以用来定位文件或流的位置。其定义如下:

type Seeker interface {  
    Seek(offset int64, whence int) (int64, error)  
}

Seek方法接受两个参数:

offset:相对位移量,表示从起始位置移动的字节数。

whence:起始位置,可以是以下三个常量之一:

  • io.SeekStart:从文件开头开始计算偏移量。
  • io.SeekCurrent:从当前文件指针位置开始计算偏移量。
  • io.SeekEnd:从文件末尾开始计算偏移量(此时offset通常为负数,表示向前移动)。

在这里插入图片描述

Seek方法返回两个值:

  • position:移动后的文件指针位置(相对于文件开头的字节数)。
  • err:可能发生的错误。

二、Seeker接口的应用场景

随机访问大文件:对于非常大的文件,通过Seek方法可以直接定位到文件的任意位置进行读写操作,而不需要从头开始遍历文件。

断点续传:在网络传输或文件复制等场景中,如果传输过程中断,可以通过Seek方法定位到上次传输的断点,继续传输剩余的数据。

日志文件分析:对于包含多条记录的日志文件,可以通过Seek方法快速定位到特定记录的位置,进行日志分析或错误排查。

三、Seeker接口的使用示例

以下是一个结合具体案例的示例代码,展示了如何使用Seeker接口来定位文件位置并进行读写操作。

File对象实现了Seeker接口

在这里插入图片描述

file对象可以直接调用Seek方法

我们先看下a.txt文件

在这里插入图片描述

代码示例:

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    // 读取文件
    file, _ := os.OpenFile("F:\\goworks\\src\\jingtian\\yufa\\io操作\\a.txt", os.O_RDWR, os.ModePerm)
    // defer close
    defer file.Close()

    // 测试seek
    // 相对开始位置。io.SeekStart
    // 相对于文件末尾, io.SeekEnd
    // func (f *File) Seek(offset int64, whence int) (ret int64, err error)
    //相对于开始位置,光标偏移两个字节
    file.Seek(2, io.SeekStart)
    //创建一个字节的buffer
    buf := []byte{0}
    file.Read(buf)

    fmt.Println(string(buf)) // n

    //Read读了一个字节, 光标现在在3这个位置
    // 相对于当前位置
    file.Seek(3, io.SeekCurrent)
    file.Read(buf)

    fmt.Println(string(buf)) // a

    // 在结尾追加内容
    //相对于结束位置偏移0,光标就设在了结束位置
    file.Seek(0, io.SeekEnd)
    //写入内容
    file.WriteString("hahahaha")
}

运行

在这里插入图片描述

再看下a.txt,可见在末尾写入了我们指定的内容

在这里插入图片描述

四、断点续传

断点续传是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载。

go语言实现断点续传的思路:

使用临时文件记录中断位置.

1.文件上传时,先创建上传一个新的文件

2.创建记录中断位置的临时文件,需要记住上一次传递了多少数据、temp.txt

3.设置文件读写偏移量,如果被暂停或者中断了,我们就可以读取这个temp.txt的记录,恢复上传

4.上传完成后,删除临时文件

在这里插入图片描述

package main

import (
    "fmt"
    "io"
    "os"
    "strconv"
)

// 断点续传
func main() {

    // 传输源文件地址
    srcFile := "D:\\downloads\\mingw.7z"
    // 传输的目标位置
    destFile := "F:\\goworks\\src\\jingtian\\yufa\\io操作\\server\\mingw.7z"
    // 临时记录文件
    tempFile := "F:\\goworks\\src\\jingtian\\yufa\\io操作\\temp.txt"

    // 创建对应的file对象,连接起来
    file1, _ := os.Open(srcFile)
    file2, _ := os.OpenFile(destFile, os.O_CREATE|os.O_RDWR, os.ModePerm)
    file3, _ := os.OpenFile(tempFile, os.O_CREATE|os.O_RDWR, os.ModePerm)
    defer file1.Close()
    defer file2.Close()
    fmt.Println("file1/2/3 文件连接建立完毕")

    // 1、读取temp.txt
    file3.Seek(0, io.SeekStart)
    buf := make([]byte, 1024)
    n, _ := file3.Read(buf) //这里的n是读取file3中的字符的个数,比如1024,得到的n是4.所以要借助string转
    //查看返回的n的数据类型
    fmt.Printf("查看n的数据类型%T\n", n)
    fmt.Println("n的值为", n)

    // 2、先转换成string,然后再转换成数字。
    countStr := string(buf[:n])
    count, _ := strconv.ParseInt(countStr, 10, 64)
    fmt.Println("temp.txt中记录的值为:", count) // 5120

    // 3、设置读写的偏移量,offset是int64数据类型
    file1.Seek(count, io.SeekStart)
    file2.Seek(count, io.SeekStart)
    fmt.Println("file1/2 光标已经移动到了目标位置")

    // 4、开始读写(复制、上传)
    bufData := make([]byte, 1024)
    // 5、需要记录读取了多少个字节
    total := int(count)

    for {
        fmt.Println("传输了,", total)
        // 读取数据
        readNum, err := file1.Read(bufData)
        if err == io.EOF || readNum == 0 { // file1 读取完毕了
            fmt.Println("文件传输完毕了")
            //上传完文件再关闭临时文件file3
            file3.Close()
            os.Remove(tempFile)
            break
        }

        // 向目标文件中写入数据,返回写的字节数和错误
        writeNum, err := file2.Write(bufData[:readNum])

        // 将写入数据放到 total中, 在这里total 就是传输的进度
        total = total + writeNum

        // temp.txt 存放临时记录数据
        file3.Seek(0, io.SeekStart) // 将光标重置到开头
        //将数字转换成字符串写入,这里total逐渐变大不存在覆盖不完的问题。如果存在覆盖不完问题,使用os.Truncate(fileName, 0)来清空文件内容
        // os.Truncate(fileName, 0) 截取指定长度字节的内容,其余内容会被删除
        file3.WriteString(strconv.Itoa(total))

        //模拟断电
        //if total > 10000 {
        //    panic("断电了")
        //}

    }

}

在这里插入图片描述

模拟传输过程中出现问题,比如断电

在这里插入图片描述

恢复电后继续上传

在这里插入图片描述

以上就是Go语言中Seeker接口的用法详解的详细内容,更多关于Go Seeker接口用法的资料请关注脚本之家其它相关文章!

相关文章

  • Go 1.21新增的slices包中切片函数用法详解

    Go 1.21新增的slices包中切片函数用法详解

    Go 1.21新增的 slices 包提供了很多和切片相关的函数,可以用于任何类型的切片,本文通过代码示例为大家介绍了部分切片函数的具体用法,感兴趣的小伙伴可以了解一下
    2023-08-08
  • 一文带你了解Go中的内存对齐

    一文带你了解Go中的内存对齐

    一旦涉及到较为底层的编程,特别是与硬件交互,内存对齐是一个必修的课题,所以这篇文章小编就想来和大家聊一聊Go语言中的内存对齐,希望对大家有所帮助
    2023-10-10
  • GO语言延迟函数defer用法分析

    GO语言延迟函数defer用法分析

    这篇文章主要介绍了GO语言延迟函数defer用法,较为详细的分析了GO语言的特性与具体用法,并给出了一个比较典型的应用实例,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • Golang环境变量设置和查看工具go env详解

    Golang环境变量设置和查看工具go env详解

    go env 是 Go 工具链中的一个命令,用于设置和查看当前 Golang 环境的相关信息,对于理解、编译和运行 Golang 程序非常有用,本文就给大家简单的介绍一下Golang环境变量设置和查看工具go env,需要的朋友可以参考下
    2023-07-07
  • golang实现浏览器导出excel文件功能

    golang实现浏览器导出excel文件功能

    这篇文章主要介绍了golang实现浏览器导出excel文件功能,文章通过golang导出excel文件返回给web,实现浏览器导出excel文件功能,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-03-03
  • 利用Go语言搭建WebSocket服务端方法示例

    利用Go语言搭建WebSocket服务端方法示例

    这篇文章主要给大家介绍了利用Go语言搭建WebSocket服务端方法,文中通过示例代码介绍的非常详细,需要的朋友们可以参考借鉴,下面来一起看看吧。
    2017-04-04
  • GoLang中生成UUID唯一标识的实现方法

    GoLang中生成UUID唯一标识的实现方法

    UUID是让分散式系统中的所有元素,都能有唯一的辨识信息,本文主要介绍了GoLang中生成UUID唯一标识的实现方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08
  • 优雅使用GoFrame共享变量Context示例详解

    优雅使用GoFrame共享变量Context示例详解

    这篇文章主要为大家介绍了优雅使用GoFrame共享变量Context示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • golang实现通过smtp发送电子邮件的方法

    golang实现通过smtp发送电子邮件的方法

    这篇文章主要介绍了golang实现通过smtp发送电子邮件的方法,实例分析了Go语言基于SMTP协议发送邮件的相关技巧,需要的朋友可以参考下
    2016-07-07
  • go语言中fallthrough的用法说明

    go语言中fallthrough的用法说明

    这篇文章主要介绍了go语言中fallthrough的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05

最新评论