Go语言关于路径的操作有pathfilepath两个包。他们都可以处理路径相关操作,但你是否疑惑过这两个包该用哪个?它们有什么区别呢?小小的脑袋充满大大的疑惑呢。

它们的区别其实看看源码就明白了,path.Dir源码在path/path.gofilepath.Dir源码在path/filepath/path.go

path/path.go文件开头有这样一段注释:

// Package path implements utility routines for manipulating slash-separated
// paths.
//
// The path package should only be used for paths separated by forward
// slashes, such as the paths in URLs. This package does not deal with
// Windows paths with drive letters or backslashes; to manipulate
// operating system paths, use the path/filepath package.

翻译过来就是说:path包提供了斜线分隔路径的常规操作。

但是,它只能用来处理正斜杠(/)分隔的路径。不能处理带有驱动符或反斜杠(\)的Windows路径,要操作不同操作系统的路径,请使用path/filepath包。

如何快速区分正斜杠和反斜杠呢?
\|/:往左偏的是反斜杠,往右偏的正斜杠。左反右正,右撇子表示很赞。

如果对 驱动符 感到疑惑,请看后面。

盲猜在path/filepath/path.go文件开头也有一段注释:

// Package filepath implements utility routines for manipulating filename paths
// in a way compatible with the target operating system-defined file paths.
//
// The filepath package uses either forward slashes or backslashes,
// depending on the operating system. To process paths such as URLs
// that always use forward slashes regardless of the operating
// system, see the path package.

翻译过来是:filepath包提供了兼容操作系统的路径操作。

它使用正斜杠还是反斜杠取决于操作系统。处理总是使用正斜杠的路径(如URL),请参见path包。

看完注释其实已经很清楚了,在处理路径时,应尽量使用filepath包,处理url时,使用path包。

为了呼应标题,我们来看看Dir函数的一些细节。

首先是path包的实现:

func Dir(path string) string {dir, _ := Split(path)return Clean(dir)
}func Split(path string) (dir, file string) {i := strings.LastIndex(path, "/")return path[:i+1], path[i+1:]
}

path包的Dir函数简单粗暴,直接以最后一个/切分路径,然后清理。关于Clean函数,可以看看它的注释:

// Clean returns the shortest path name equivalent to path
// by purely lexical processing. It applies the following rules
// iteratively until no further processing can be done:
//
//  1. Replace multiple slashes with a single slash.
//  2. Eliminate each . path name element (the current directory).
//  3. Eliminate each inner .. path name element (the parent directory)
//     along with the non-.. element that precedes it.
//  4. Eliminate .. elements that begin a rooted path:
//     that is, replace "/.." by "/" at the beginning of a path.
//
// The returned path ends in a slash only if it is the root "/".
//
// If the result of this process is an empty string, Clean
// returns the string ".".
//
// See also Rob Pike, ``Lexical File Names in Plan 9 or
// Getting Dot-Dot Right,''
// https://9p.io/sys/doc/lexnames.html

Clean函数通过词法处理得到一个和原路径等价的最短路径。规则如下:

  1. 多个连续斜杠变成一个斜杠
  2. 消除.路径
  3. 消除内部的..以及(紧挨)..前面的(一个)路径
  4. 消除根路径(/)后的..,即(开头的)/..替换成/

只有根路径才会以斜杠结尾,换句话说Clean返回的路径会去掉末尾的斜杠。
如果参数是空字符串,Clean函数返回.

再来看看filepath包中Dir的实现:

func Dir(path string) string {vol := VolumeName(path)i := len(path) - 1 //记录最后一个分隔符下标for i >= len(vol) && !os.IsPathSeparator(path[i]) { //寻找最后一个分隔符i--}dir := Clean(path[len(vol) : i+1]) //路径清理if dir == "." && len(vol) > 2 {// must be UNCreturn vol}return vol + dir
}

这段逻辑也很简单:

  1. 首先获取路径的卷名
  2. 在卷名之后的路径中找到最后一个分隔符
  3. 对卷名和最后一个分隔符之间的路径做清理
  4. 拼接卷名和清理后的路径

此处Clean函数要比path包的稍微复杂,单基本规则还是一样的。

这里提到的卷名,包括前面的驱动符,是否让你感到疑惑呢?它们其实是同一个东西,看看VolumeName函数的实现就会明白了。

// VolumeName returns leading volume name.
// Given "C:\foo\bar" it returns "C:" on Windows.
// Given "\\host\share\foo" it returns "\\host\share".
// On other platforms it returns "".
func VolumeName(path string) string {return path[:volumeNameLen(path)]
}// volumeNameLen returns length of the leading volume name on Windows.
// It returns 0 elsewhere.
func volumeNameLen(path string) int {if len(path) < 2 {return 0}// with drive letterc := path[0]if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {return 2}// is it UNC? https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspxif l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&!isSlash(path[2]) && path[2] != '.' {// first, leading `\\` and next shouldn't be `\`. its server name.for n := 3; n < l-1; n++ {// second, next '\' shouldn't be repeated.if isSlash(path[n]) {n++// third, following something characters. its share name.if !isSlash(path[n]) {if path[n] == '.' {break}for ; n < l; n++ {if isSlash(path[n]) {break}}return n}break}}}return 0
}

在Windows上其实就是你的盘符,比如C:VolumeName通过卷名长度来切片路径得到卷名,卷名长度通过volumeNameLen函数获取,在Windows上就是2。

这里涉及到一个东西叫做通用命名规范,英文名叫UNC (Universal Naming Convention)。这是一个通用的目录命名规范,我们没搜到规范原文,基本上你见到的目录都是遵循这个规范的,感兴趣的可以去搜索,各显神通吧。

path.Dir? filepath.Dir? 傻傻分不清楚相关推荐

  1. Spark on Hive Hive on Spark傻傻分不清?

    Spark on Hive? Hive on Spark傻傻分不清? 1 spark on hive Spark on hive,是spark计算引擎依托hive data source,spark ...

  2. 傻傻分不清的Manifest

    在前端,说到manifest,其实是有歧义的,就我了解的情况来说,manifest可以指代下列含义: html标签的manifest属性: 离线缓存(目前已被废弃) PWA: 将Web应用程序安装到设 ...

  3. JS魔法堂:属性、特性,傻傻分不清楚

    一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...

  4. ASP.NET MVC涉及到的5个同步与异步,你是否傻傻分不清楚?[下篇]

    关于ASP.NET MVC对请求的处理方式(同步或者异步)涉及到的五个组件,在<上篇>中我们谈了三个(MvcHandler.Controller和ActionInvoker),现在我们来谈 ...

  5. 科普 | Shell中傻傻分不清楚的TOP3

    近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Command Line>PDF链接.感谢老大不 ...

  6. 国家电网和南方电网还傻傻分不清?

    参看:都2020年了,国家电网和南方电网还傻傻分不清? 一.名称不同 一个叫南方电网,一个叫国家电力电网,虽然都是电网,但是区别还是很大的 而且成立时间不一样:国家电力电网有限公司成立于2002年12 ...

  7. cdn厂商 同兴万点_同兴万点:TXNetworks和CDNetworks让我们傻傻分不清

    原标题:同兴万点:TXNetworks和CDNetworks让我们傻傻分不清 在2008年2月25日成立的同兴万点,公司全称为同兴万点(北京)网络技术有限公司(TXNetworks),一直专注于CDN ...

  8. 2021年了,`IEnumerator`、`IEnumerable`接口还傻傻分不清楚?

    IEnumerator.IEnumerable这两个接口单词相近.含义相关,傻傻分不清楚. 入行多年,一直没有系统性梳理这对李逵李鬼. 最近本人在怼着why神的<其实吧,LRU也就那么回事> ...

  9. 动态ram依靠什么存储信息_ROM、RAM、DRAM、SRAM和FLASH傻傻分不清

    ROM.RAM.DRAM.SRAM和FLASH各类储存器在电脑.手机.电子设备.嵌入式设备及相应的开发中普遍应用的,但是很多还是傻傻分不清楚.下面就简单介绍下这几个吧! ROM和RAM ROM:只读存 ...

最新文章

  1. 【常见Web应用安全问题】
  2. ADSL使用注意事项
  3. 基于Python语言使用RabbitMQ消息队列(一)
  4. .NET Core + Spring Cloud:服务注册与发现
  5. 这8个中国天文台你肯定不认识!
  6. php xml cdata 解析,![CDATA[文本内容]]代表的意思
  7. 2020 年物联网设备达 500 亿台!AI、区块链技术加持,优秀开发者稀缺!
  8. 2018年股票操作策略记录(1)
  9. Struts 标签 —— Bean 标签
  10. 传奇源码分析-客户端(WindHorn简述和传奇文件格式分析)
  11. CHIP-seq 分析笔记
  12. [Java]面向对象编程
  13. win7计算机进行重镜像,win7镜像重装系统图文教程
  14. train data 和 model bias 对 Mutilayer Perceptrons 的影响
  15. 罗克韦尔AB PLC(RSLogix 5000)在线修改程序的具体方法示例
  16. git拆分子目录作为新仓库并保留log记录
  17. ismobile什么意思_英语is是什么意思?
  18. ffplay工具命令使用技巧浅析
  19. 第一章 学习Java的建议
  20. 《漫画傅里叶解析》笔记(6)

热门文章

  1. git客户端安装(windows)
  2. SMBus和I2C通信协议主机的Verilog实现
  3. geetest文件夹什么意思_极验geetest的使用
  4. matlab如何打开dcm_MATLAB结合Unreal Engine构建用以自动驾驶仿真测试的逼真驾驶场景...
  5. 重磅!浙大开设区块链课程,影响70%的程序员?
  6. 八大排序详解-超详细
  7. 强化学习--马尔可夫决策过程学习笔记
  8. 在东软正式培训的第一周
  9. Aruba 无线配置
  10. Unity_Shader(简易的卡通渲染)