golang如何判断文件是否存在

 更新时间:2024年11月26日 11:35:20   作者:apocelipes  
判断一个文件是否存在是一个相当常见的需求,在golang中也有多种方案实现这一功能,下面就跟随小编一起学习一下具体的实现方法吧

判断一个文件是否存在是一个相当常见的需求,在golang中也有多种方案实现这一功能。

现在我们介绍其中两种最常用也是最简单的实现,第一种将是跨平台通用的,而第二种则在POSIX平台上通用。

跨平台实现

跨平台实现的思路很简单,如果某个文件不存在,那么使用os.Lstat就一定会返回error,只要判断error是否代表文件不存在即可。

也许你注意到了有些代码会使用os.Open来完成上述工作,不过最好不要这么做,因为虽然两者完成的功能没有区别,但open和stat的调用开销是不同的,后者要小于前者,而且对于判断文件是否存在,检查它的元数据要比直接尝试打开它更加合理。

那么来看看实现的代码:

func FileExist(path string) bool {
  _, err := os.Lstat(path)
  return !os.IsNotExist(err)
}

代码很简单,对于Windows/Linux/MacOS等是通用的,一般没有特殊需求我也比较推荐这种实现。

POSIX平台实现

如果你的程序是面向POSIX平台的(例如UNIX、Linux等),那么还有一种更简单的方案——syscall.Access

syscall.Access提供了用户检查文件元信息的手段,通常它被用来检查文件权限以及文件的存在性。

通过使用syscall.F_OK标志检查文件,如果不存在则会返回和os.Lstat一样的error:

func FileExist(path string) bool {
  err := syscall.Access(path, syscall.F_OK)
  return !os.IsNotExist(err)
}

这种实现的最大优势在于它简单而直观,但是它无法在Windows上使用。

一些提示

首先当我们的FileExist返回true时,其实文件并不一定存在。

当我们对目标path中的某一部分没有可读权限时,os.Lstatsyscall.Access同样会返回error,不过这个error不会让os.IsNotExist返回true。

当文件不存在而你对文件所在的目录或者它的上层目录没有访问权限时,FileExist依旧会返回true,bug就在这时发生了。所以重要的一点是在判断文件是否存在前应该先判断自己对文件及其路径是否有访问权限

其次syscall.Access只会使用运行程序的用户的uid和gid,这会导致setuid之类的权限失效,通常来说这是没什么问题的,然而posix平台上一般都会考虑euid和egid,因此你可能需要使用syscall.Faccessat做代替。你需要在深思熟虑后使用合适的系统调用。

性能测试

最后我们看看两个方案的性能,我们以os.Open做为基准,分别测试先文件存在和不存在时的性能表现:

func checkWithOpen(path string) bool {
	f, err := os.Open(path)
	if err != nil {
		return false
	}
	f.Close()
	return true
}

func checkWithLstat(path string) bool {
	_, err := os.Lstat(path)
	return !os.IsNotExist(err)
}

func checkWithAccess(path string) bool {
        err := syscall.Access(path, syscall.F_OK)
	return !os.IsNotExist(err)
}

func BenchmarkNotExists(b *testing.B) {
	for range b.N {
		checkWithOpen("/home/apocelipes/no-")
	}
}

func BenchmarkNotExistsLstat(b *testing.B) {
	for range b.N {
		checkWithLstat("/home/apocelipes/no-")
	}
}

func BenchmarkNotExistsAccess(b *testing.B) {
	for range b.N {
		checkWithAccess("/home/apocelipes/no-")
	}
}

func BenchmarkExists(b *testing.B) {
	for range b.N {
		checkWithOpen("/home/apocelipes/.zshrc")
	}
}

func BenchmarkExistsLstat(b *testing.B) {
	for range b.N {
		checkWithLstat("/home/apocelipes/.zshrc")
	}
}

func BenchmarkExistsAccess(b *testing.B) {
	for range b.N {
		checkWithAccess("/home/apocelipes/.zshrc")
	}
}

这是结果:

测试使用的文件系统类型是XFS。

可以看到open是最慢的,lstat比access慢了16%左右。从结果里也可以看到lstat需要额外返回一个os.FileInfo结构导致了额外的内存分配,所以整体上速度更慢。

但考虑到跨平台以及兼容性,使用os.Lstat是更常见的做法。

以上就是golang如何判断文件是否存在的详细内容,更多关于go判断文件是否存在的资料请关注脚本之家其它相关文章!

相关文章

  • Go语言切片(Slice)深度剖析与应用实战

    Go语言切片(Slice)深度剖析与应用实战

    在Go语言中,切片(Slice)是一种非常强大且灵活的数据结构,它基于数组但又提供了动态调整大小的能力,本文将结合实际案例,详细介绍Go语言中切片的声明、初始化、操作、扩容等用法,需要的朋友可以参考下
    2024-09-09
  • Golang 语言高效使用字符串的方法

    Golang 语言高效使用字符串的方法

    这篇文章主要介绍了Golang 语言高效使用字符串的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Go语言实现配置热加载的方法分享

    Go语言实现配置热加载的方法分享

    web项目,经常需要热启动各种各样的配置信息,一旦这些服务发生变更,我们需要重新启动web server,以使配置生效,实现配置热加载,本文为大家整理了几个方法实现这个需求,需要的可以参考下
    2023-05-05
  • 一文详解Golang中的errors包

    一文详解Golang中的errors包

    在 Golang 中,errors 包是用于处理错误的标准库, errors 包提供的功能比较简单,使用起来非常方便,接下来就具体讲解一下 errors 包提供的几个函数,感兴趣的小伙伴跟着小编一起来看看吧
    2023-07-07
  • 使用Go语言实现配置文件热加载功能

    使用Go语言实现配置文件热加载功能

    这篇文章主要介绍了使用Go语言实现配置文件热加载功能,以及配置文件热加载包的实现思路,需要的朋友可以参考下
    2018-03-03
  • 高效封禁:利用Go封装功能,提升封禁操作效率

    高效封禁:利用Go封装功能,提升封禁操作效率

    在网络安全领域,封禁操作是一项重要的任务,用于阻止恶意行为和保护系统安全,而利用Go语言封装功能可以提升封禁操作的效率,Go语言具有高效的并发性能和简洁的语法,使得开发者可以快速构建高性能的封禁系统,
    2023-10-10
  • 在go文件服务器加入http.StripPrefix的用途介绍

    在go文件服务器加入http.StripPrefix的用途介绍

    这篇文章主要介绍了在go文件服务器加入http.StripPrefix的用途介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 一文详解go同步协程的必备工具WaitGroup

    一文详解go同步协程的必备工具WaitGroup

    这篇文章主要为大家介绍了一文详解go同步协程的必备工具WaitGroup使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Golang收支记账程序详细编写过程

    Golang收支记账程序详细编写过程

    这篇文章主要介绍了Golang实现收支记账程序流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • Golang 操作 Kafka 如何设置消息的失效时间

    Golang 操作 Kafka 如何设置消息的失效时间

    在使用 Golang 操作 Kafka 时,你可以使用 Sarama 库来设置消息的失效时间,这篇文章主要介绍了Golang操作Kafka设置消息的失效时间,需要的朋友可以参考下
    2023-06-06

最新评论