(二)常用内置函数

文件系统

当前文件偏移量【指针】 Current Offset

当打开或者创建一个文件时,都会有文件偏移量,用以度量从文件开始处计算的字节数,通常,读,写操作都是从当前文件偏移量开始,并使偏移量增加所读写的字节数.按照系统默认情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0

文件读取完毕后指针会指向文件尾部,此时再进行读取是读不到东西的

io.Copy(dst io.Writer, src io.Reader) (written int64, err error)

接受两个参数:一个可写源,一个可读源

go 复制代码
func FileOperate() {
	sourceFile, err := os.Open("./fileSys/demo.txt")
	if err != nil {
		fmt.Println(err)
	}

	targetFile, err := os.Create("./fileSys/demo1.txt")
	targetFile2, err := os.Create("./fileSys/demo2.txt")

	io.Copy(targetFile, sourceFile)  // 成功将demo.txt的内容复制到了demo1
	io.Copy(targetFile2, sourceFile) // 没有复制到任何东西
}

上面的代码,执行过一次Copy后,sourceFile的指针指向文件尾部,再进行赋值,读取不到任何内容了,想要继续copy到内容,需要将文件指针指向文件头部:

go 复制代码
...
...
io.Copy(targetFile, sourceFile)
sourceFile.Seek(0,io.SeekStart) // 将文件指针移到头部
io.Copy(targetFile2, sourceFile)

// 或者调用os.Open()再次打开文件

File.ReadFrom(r io.Reader) (n int64, err error)

将读取的数据写入到文件中,和io.Copy类似,io.Copy内部一般也是调用此方法,进行操作

go 复制代码
func FileOperate() {
	sourceFile, err := os.Open("./fileSys/demo.txt")
	if err != nil {
		fmt.Println(err)
	}

	targetFile, err := os.Create("./fileSys/demo1.txt")
	targetFile2, err := os.Create("./fileSys/demo2.txt")

	targetFile.ReadFrom(sourceFile)
	sourceFile.Seek(0, io.SeekStart)// 指针重置到文件头部
	targetFile2.ReadFrom(sourceFile)
}

File.ReadAt(b []byte, off int64) (n int, err error)

从文件off指定偏移位置尝试读取n个字节长度的内从到切片b中,如果读取成功返回读取的长度n,失败返回err,这个方法不会自动更新文件的偏移量,下次读取依旧从指定的位置开始

File.Read(b []byte) (n int, err error)

从文件头部开始读取n个字节的内容到切片b中,如果读取成功返回读取的长度n,失败返回err,这个方法会自动更新文件偏移量,下一次将从上次一读取结束的地方开始

File.Write(b []byte) (n int, err error)

向文件中写入内容

go 复制代码
// 同样以上面文件copy为例
func FileOperate() error {

	sourceFile, err := os.Open("./fileSys/demo.txt")
	if err != nil {
		fmt.Println(err)
	}

	sourceFileInfo, err := sourceFile.Stat()

	if err != nil {
		return err
	}

	buffer := make([]byte, sourceFileInfo.Size())

	sourceFile.Read(buffer)

	targetFile, err := os.Create("./fileSys/demo1.txt")
	targetFile2, err := os.Create("./fileSys/demo2.txt")

	targetFile.Write(buffer)
	targetFile2.Write(buffer)
	return nil
}
  • 上面方式读取大文件可能会有性能问题,换另一种方式:
go 复制代码
func FileOperate() error {

	sourceFile, err := os.Open("./fileSys/demo.txt")
	if err != nil {
		fmt.Println(err)
	}

	targetFile, err := os.Create("./fileSys/demo1.txt")
	targetFile2, err := os.Create("./fileSys/demo2.txt")

	buffer := make([]byte, 1024)

	for {
		n, err := sourceFile.Read(buffer)
		if err != nil {
			break
		}
		if n > 0 {
			// 可能读不满1024个字节,所以要根据实际截取
			targetFile.Write(buffer[0:n])
			targetFile2.Write(buffer[0:n])
		}
	}

	return nil
}

判断文件、目录是否存在

go 复制代码
if file, err := os.Stat("./fileSys/asdf/demo45.txt"); err == nil || os.IsExist(err) {
    fmt.Println("文件存在", file)
    return
} 
fmt.Println("文件不存在")
// 或者使用os.IsNotExist判断

其他内置函数

时间格式化

骚气的格式化方法,和js不同,不能用YYYY-MM-DD HH:mm:ss的形式,而是要传入一个指定格式实际日期模板,例如:2022-01-02 15:20:32
尤其注意时分秒格式化:时间模板3代表12小时制,15代表24小时制

go 复制代码
// 获取当前时间并格式化成指定日期(12小时制)
t := time.Now().Format("20060102_030405")
fmt.Println(t) // 输出:20230829_111650

// 获取当前时间并格式化成指定日期(24小时制)
t := time.Now().Format("20060102_150405")
fmt.Println(t) // 输出:20230829_111650
相关推荐
Grassto1 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto3 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室4 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题4 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
啊汉6 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想
asaotomo6 天前
一款 AI 驱动的新一代安全运维代理 —— DeepSentry(深哨)
运维·人工智能·安全·ai·go
码界奇点7 天前
基于Gin与GORM的若依后台管理系统设计与实现
论文阅读·go·毕业设计·gin·源代码管理
迷迭香与樱花7 天前
Gin 框架
go·gin
只是懒得想了7 天前
用Go通道实现并发安全队列:从基础到最佳实践
开发语言·数据库·golang·go·并发安全
fenglllle8 天前
使用fyne做一个桌面ipv4网段计算程序
开发语言·go