Golang实现IO操作

 更新时间:2024年05月14日 08:29:01   作者:两片空白  
本文主要介绍了Golang实现IO操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 输入输出的底层原理

终端其实是一个文件(Linux下一切皆文件),相关实例如下:

  • os.Stdin:标准输出的文件实例,类型为*File
  • os.Stdout:标准输入的文件实例,类型为*File
  • os.Stderr:标准错误输出的文件实例,类型为*File

以文件方式操作终端:

package main

import (
	"os"
)

func main() {
	var buf []byte
	os.Stdin.Read(buf[:])             //从标准输入中读取
	os.Stdin.WriteString(string(buf)) //写入标准输入
}

2. 文件操作相关API 

根据提供的文件名创建新的文件,返回一个文件对象,默认权限0666,任何人可读可写,不可执行,如果文件存在,则会截断它(为空文件),如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。如果出错,错误底层类型是*PathError。

func Create(name string) (file *File, err error)

NewFile使用给出的Unix文件描述符和名称创建一个文件。 

func NewFile(fd uintptr, name string) *File

只读方式打开一个名称为name文件。

func Open(name string) (file *File, err error)

打开一个名为name的文件,flag是打开方式,只读或只写,不存在创建等,perm文件权限。 

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

在指定位置(相对于文件起始位置),写入byte类型的数据到文件,它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。

func (f *File) WriteAt(b []byte, off int64) (n int, err error)

向文件中写入string类型的信息到文件。

func (f *File) WriteString(s string) (ret int, err error)

从f中读取最多len(b)字节数的数据到b。

func (f *File) Read(b []byte) (n int, err error)

从f的指定位置(相对于文件起始位置),读取len(b)字节数并写入b。

func (f *File) ReadAt(b []byte, off int64) (n int, err error)

删除name指定的文件或目录。

func Remove(name string) error

 3. 打开和关闭文件

os.Open()函数能够打开一个文件,返回一个*File和一个err。对得到的文件实例调用close()方法能够关闭文件。

package main

import (
	"log"
	"os"
)

func main() {
	//只读的方式打开文件
	f, err := os.Open("./main.go")
	if err != nil {
		log.Println("open main.go file fail")
		return
	}
	//关闭文件
	defer f.Close()
}

4. 写文件

package main

import (
	"log"
	"os"
)

func main() {
	//可读可写的方式创建一个文件
	f, err := os.Create("./xx.txt")
	if err != nil {
		log.Println("create file fail")
		return
	}
	defer f.Close()

	for i := 0; i < 5; i++ {
		f.Write([]byte("ab\n"))
		f.WriteString("ab\n")
	}
}

5. 读文件

文件读取可以用file.Read()和file.ReadAt(),读到文件末尾会返回io.EOF的错误。

package main

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

func main() {
	f, err := os.Open("./xx.txt")
	if err != nil {
		log.Println("open file fail")
		return
	}
	defer f.Close()

	var content []byte
	for {
		var buf [128]byte
		n, err := f.Read(buf[:])
		if err == io.EOF {
			//读到文件末尾
			break
		}
		if err != nil {
			log.Println("Read file fail", err)
			return
		}
		content = append(content, buf[:n]...) //buf[:n]切片被打散传入
	}
	fmt.Println(string(content))
}

“…”的用法:三个点“...”其实是go的一种语法糖(糖衣语法)

  • 第一个用法主要是用于函数有多个不定参数的情况,表示为可变参数,可以接受任意个数但相同类型的参数。
  • 第二个用法是slice可以被打散进行传递。

 6. 拷贝文件

package main

import (
	"io"
	"log"
	"os"
)

func main() {
	f1, err := os.Open("./xx.txt")
	if err != nil {
		log.Println("open xx.txt file fail", err)
		return
	}
	defer f1.Close()
	f2, err := os.Create("./abc.txt")
	if err != nil {
		log.Println("create file fail ", err)
		return
	}
	defer f2.Close()

	for {
		var buf [128]byte
		n, err := f1.Read(buf[:])
		if err == io.EOF {
			log.Println("读取完毕")
			break
		}
		if err != nil {
			return
		}

		f2.Write(buf[:n])
	}
}

7. bufio

  • bufio包实现了带缓冲区的读写,是对文件读写的封装。
  • bufio缓冲写数据。

  • bufio读数据 ,bufio先把数据读/写到缓冲区,达到某一上限,会刷新到文件中,也可以强制刷新。
package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
)

func wr() {
	f, err := os.OpenFile("./xxx.txt", os.O_CREATE|os.O_WRONLY, 0664)
	if err != nil {
		log.Println("open file fail ", err)
		return
	}
	defer f.Close()
    //获取writer对象
	writer := bufio.NewWriter(f)
	for i := 0; i < 5; i++ {
		writer.WriteString("hello\n")
	}
	//刷新缓冲区,强制写入
	writer.Flush()
}

func rd() {
	f, err := os.Open("./xxx.txt")
	if err != nil {
		log.Println("open file fail")
		return
	}
	defer f.Close()

    //获取reader对象
	reader := bufio.NewReader(f)
	var content []byte
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			log.Println("读取完毕")
			break
		}
		if err != nil {
			return
		}
		content = append(content, line...)
	}
	fmt.Println(string(content))
}

func main() {
	wr()
	rd()
}

8. ioutil工具包

  • 工具包写文件
  • 工具包读文件
package main

import (
	"fmt"
	"io/ioutil"
	"log"
)

func wr() {
	err := ioutil.WriteFile("./xxxx.txt", []byte("hello world!"), 0666)
	if err != nil {
		log.Println("err")
		return
	}
}

func rd() {
	data, err := ioutil.ReadFile("./xxxx.txt")
	if err != nil {
		log.Println("err")
		return
	}
	fmt.Println(string(data))
}

func main() {
	wr()
	rd()
}

9. 例子

        实现cat命令

package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
)

func cat(reader *bufio.Reader) {
	for {
		buf, err := reader.ReadBytes('\n') //注意是字符
		if err == io.EOF {
			break
		}
		fmt.Fprintf(os.Stdout, "%s", string(buf))
	}
}

func main() {
	flag.Parse()
	if flag.NArg() == 0 {
		cat(bufio.NewReader(os.Stdin))
	} else {
		for i := 0; i &lt; flag.NArg(); i++ {
			f, err := os.Open(flag.Arg(i))
			if err != nil {
				log.Printf("open file %s fail, err %v\n", flag.Arg(i), err)
				continue
			}
			cat(bufio.NewReader(f))
			f.Close()
		}
	}
}

到此这篇关于Golang实现IO操作的文章就介绍到这了,更多相关Golang IO操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言并发之原子操作详解

    Go语言并发之原子操作详解

    代码中的加锁操作因为涉及内核态的上下文切换会比较耗时、代价比较高。针对基本数据类型我们还可以使用原子操作来保证并发安全,本文就来和大家详细聊聊,需要的可以参考下
    2022-12-12
  • 详解Go中gin框架如何实现带颜色日志

    详解Go中gin框架如何实现带颜色日志

    当我们在终端上(比如Goland)运行gin框架搭建的服务时,会发现输出的日志是可以带颜色的,那这是如何实现的呢?本文就来和大家简单讲讲
    2023-04-04
  • golang判断chan channel是否关闭的方法

    golang判断chan channel是否关闭的方法

    这篇文章主要介绍了golang判断chan channel是否关闭的方法,结合实例形式对比分析了Go语言判断chan没有关闭的后果及关闭的方法,需要的朋友可以参考下
    2016-07-07
  • golang chan传递数据的性能开销详解

    golang chan传递数据的性能开销详解

    这篇文章主要为大家详细介绍了Golang中chan在接收和发送数据时因为“复制”而产生的开销,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2024-01-01
  • Linux中Go环境配置和GoModule常用操作

    Linux中Go环境配置和GoModule常用操作

    这篇文章主要介绍了Linux中Go环境配置和GoModule,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • Gin 框架快速创建静态文件下载Web服务

    Gin 框架快速创建静态文件下载Web服务

    本文主要介绍了Gin 框架快速创建静态文件下载Web服务,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Go 高效截取字符串的一些思考

    Go 高效截取字符串的一些思考

    这篇文章主要介绍了Go 高效截取字符串的一些思考,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • golang中sync.Map并发创建、读取问题实战记录

    golang中sync.Map并发创建、读取问题实战记录

    这篇文章主要给大家介绍了关于golang中sync.Map并发创建、读取问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • golang http连接复用方法

    golang http连接复用方法

    今天小编就为大家分享一篇golang http连接复用方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-07-07
  • 解决Go语言数据库中null值的问题

    解决Go语言数据库中null值的问题

    这篇文章主要介绍了解决Go语言数据库中null值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12

最新评论