path.Dir? filepath.Dir? 傻傻分不清楚
Go语言关于路径的操作有path
和filepath
两个包。他们都可以处理路径相关操作,但你是否疑惑过这两个包该用哪个?它们有什么区别呢?小小的脑袋充满大大的疑惑呢。
它们的区别其实看看源码就明白了,path.Dir
源码在path/path.go
,filepath.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
函数通过词法处理得到一个和原路径等价的最短路径。规则如下:
- 多个连续斜杠变成一个斜杠
- 消除
.
路径- 消除内部的
..
以及(紧挨)..
前面的(一个)路径- 消除根路径(
/
)后的..
,即(开头的)/..
替换成/
只有根路径才会以斜杠结尾,换句话说
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
}
这段逻辑也很简单:
- 首先获取路径的卷名
- 在卷名之后的路径中找到最后一个分隔符
- 对卷名和最后一个分隔符之间的路径做清理
- 拼接卷名和清理后的路径
此处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? 傻傻分不清楚相关推荐
- Spark on Hive Hive on Spark傻傻分不清?
Spark on Hive? Hive on Spark傻傻分不清? 1 spark on hive Spark on hive,是spark计算引擎依托hive data source,spark ...
- 傻傻分不清的Manifest
在前端,说到manifest,其实是有歧义的,就我了解的情况来说,manifest可以指代下列含义: html标签的manifest属性: 离线缓存(目前已被废弃) PWA: 将Web应用程序安装到设 ...
- JS魔法堂:属性、特性,傻傻分不清楚
一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...
- ASP.NET MVC涉及到的5个同步与异步,你是否傻傻分不清楚?[下篇]
关于ASP.NET MVC对请求的处理方式(同步或者异步)涉及到的五个组件,在<上篇>中我们谈了三个(MvcHandler.Controller和ActionInvoker),现在我们来谈 ...
- 科普 | Shell中傻傻分不清楚的TOP3
近来小姐姐又犯憨憨错误,问组内小伙伴export命令不会持久化环境变量吗?反正我是问出口了..然后小伙伴就甩给了我一个<The Linux Command Line>PDF链接.感谢老大不 ...
- 国家电网和南方电网还傻傻分不清?
参看:都2020年了,国家电网和南方电网还傻傻分不清? 一.名称不同 一个叫南方电网,一个叫国家电力电网,虽然都是电网,但是区别还是很大的 而且成立时间不一样:国家电力电网有限公司成立于2002年12 ...
- cdn厂商 同兴万点_同兴万点:TXNetworks和CDNetworks让我们傻傻分不清
原标题:同兴万点:TXNetworks和CDNetworks让我们傻傻分不清 在2008年2月25日成立的同兴万点,公司全称为同兴万点(北京)网络技术有限公司(TXNetworks),一直专注于CDN ...
- 2021年了,`IEnumerator`、`IEnumerable`接口还傻傻分不清楚?
IEnumerator.IEnumerable这两个接口单词相近.含义相关,傻傻分不清楚. 入行多年,一直没有系统性梳理这对李逵李鬼. 最近本人在怼着why神的<其实吧,LRU也就那么回事> ...
- 动态ram依靠什么存储信息_ROM、RAM、DRAM、SRAM和FLASH傻傻分不清
ROM.RAM.DRAM.SRAM和FLASH各类储存器在电脑.手机.电子设备.嵌入式设备及相应的开发中普遍应用的,但是很多还是傻傻分不清楚.下面就简单介绍下这几个吧! ROM和RAM ROM:只读存 ...
最新文章
- 【常见Web应用安全问题】
- ADSL使用注意事项
- 基于Python语言使用RabbitMQ消息队列(一)
- .NET Core + Spring Cloud:服务注册与发现
- 这8个中国天文台你肯定不认识!
- php xml cdata 解析,![CDATA[文本内容]]代表的意思
- 2020 年物联网设备达 500 亿台!AI、区块链技术加持,优秀开发者稀缺!
- 2018年股票操作策略记录(1)
- Struts 标签 —— Bean 标签
- 传奇源码分析-客户端(WindHorn简述和传奇文件格式分析)
- CHIP-seq 分析笔记
- [Java]面向对象编程
- win7计算机进行重镜像,win7镜像重装系统图文教程
- train data 和 model bias 对 Mutilayer Perceptrons 的影响
- 罗克韦尔AB PLC(RSLogix 5000)在线修改程序的具体方法示例
- git拆分子目录作为新仓库并保留log记录
- ismobile什么意思_英语is是什么意思?
- ffplay工具命令使用技巧浅析
- 第一章 学习Java的建议
- 《漫画傅里叶解析》笔记(6)