(二)常用内置函数

文件系统

当前文件偏移量【指针】 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
相关推荐
梁梁梁梁较瘦2 天前
边界检查消除(BCE,Bound Check Elimination)
go
梁梁梁梁较瘦2 天前
指针
go
梁梁梁梁较瘦2 天前
内存申请
go
半枫荷2 天前
七、Go语法基础(数组和切片)
go
梁梁梁梁较瘦2 天前
Go工具链
go
半枫荷3 天前
六、Go语法基础(条件控制和循环控制)
go
半枫荷4 天前
五、Go语法基础(输入和输出)
go
小王在努力看博客4 天前
CMS配合闲时同步队列,这……
go
Anthony_49264 天前
逻辑清晰地梳理Golang Context
后端·go
Dobby_055 天前
【Go】C++ 转 Go 第(二)天:变量、常量、函数与init函数
vscode·golang·go