文件路径操作是工具里面的常用项,周知文件类型分为 绝对路径和相对路径,最终在调用过程中运行时的相对路径在程序内部还是转换成绝对路径的。
开发工具的不同目录和子目录都有不同职能,过去经常的写法是从文件根目录,然后拼接不同的 module,在不同目录下面放一些相对路径会比较危险,因为运行时位置修改会导致路径错误,需要做防御代码。
比如原来在 L3 层目录我去调其他 L3 层的相对路径,当 L3 层被 L2 层代码引用后运行,这个相对路径就去找其他 L2 层的。
这个当下已经有了最佳的解决方案,就是相对路径写个配置放在根目录下面,提供给其他 module 使用。
有个新思路这样的,a/b/c/d,a 是项目名称根目录,b/c/d d 是第 4 级目录,原来是一路拼接过去,但是是否能反过来,想要第几层就截取第几层,但是这个优势在 5 层之内和框架不是混合作用的看不出来优势。
接下来说下开发思路,设计一个 SplitPath(str string,lv int)。
第一个参数 src/utils/report/simple/smoke/csv_to_sql.go
第二个参数 截取到第几个层级,比如截取 4 就是截取到 src/utils
这个过程中当然需要做一些容错(比如 lv 大于 str 查找到的参数),Golang 的便捷开发更多是体现在并发原语处理方面,其他方面也不算便捷。
先把这个需求分解成简单化的,比如定义个 SplitStrWord(str string,word byte) ,字符串查找关键字 然后切到关键字后面的信息
Go 语言 byte 就是 char 类型,区分单引号。
/**
字符串查找关键字 然后切到关键字后面的信息
*/
func SplitStrWord(str string,word byte)string{
pos :=0
for i:= len(str)-1;i>0;i--{
if str[i]==word{
pos =i
break
}
}
if pos>0{
pos++
}
return str[pos:]
}
func main(){
size:= "hello world"
rs := SplitStrWord(size,'w')
fmt.Println(rs)
}
这个分治出来的小功能原型,因为是从后往前找,所以用 for 循环递减。核心是 if str[i]==word{ pos ==i},这个时候 pos 就已经 find 第一次的位置了,后面 pos++ 就是递加,这是为了把当前的 word 给过滤掉。
扩展成完整的路径截断例子。
/**
路径按lv从后往前进行截取
*/
func SplitPath(pathname string,lv int)string{
count := 0
idx := 0
//find pathname字符串里面的数量
idxcount := regexp.MustCompile("/").FindAllStringIndex(pathname, -1)
if lv > len(idxcount){
return "not found"
}
for i:= len(pathname)-1;i>=0;i--{
//os.PathSeparator 等同Python的os.seq
if pathname[i] == os.PathSeparator || pathname[i] == '/'{
count++
if count ==lv{
idx =i
break //找到就退出for提高效率
}
}
}
if idx >0 {
idx++
}
return pathname[:idx]
}
func main(){
t,_:= filepath.Abs("src/utils/report/simple/smoke/csv_to_sql.go")
fmt.Println(SplitPath(t,5)) //src/
fmt.Println(SplitPath(t,7)) //not found
}
filepath.Abs 是转成绝对路径,pathname[i] == os.PathSeparator || pathname[i] == '/'支持了绝对路径和字符串其中满足一个。
FindAllStringIndex 这段是做保护,如果没找到就是-1,找到返回是一个数组,数组长度就是前面"/"出现次数,用这个次数在去做防御代码,比如输入 7,打印结果就是 not found.
如果要从前往后找,就是主体代码从 for 循环递减修改为递增,有兴趣的稍微部分代码就可以用了。