很简单的调用:
cmd := exec.Command( "TeraCopy.exe", fmt.Sprintf(`*"%s" "%s"`, copyPaths, targetDir) )
err := cmd.Start()
报错:
---------------------------
TeraCopy - Error
---------------------------
File not found:
\e:\**\tc.tmp \E:\**\b\
---------------------------
确定
---------------------------
??? 啥玩意 ???
本着出了问题先找自身原因的混帐话优良传统,控制台与 TeraCopy 软件试了各种参数,都正常……
感觉是转义出了问题,谷歌了半天,除了复制粘贴就没别的了。
米田共里淘金终于发现了一片文章:Go 在 windows 上调用本地进程传参时的一个天坑
MD ,最终 tm 还是 go 的问题,一直不敢往那想,属实被喷怕了。 摘抄一下:
On Windows, processes receive the whole command line as a single string and do their own parsing. Command combines and quotes Args into a command line string with an algorithm compatible with applications using CommandLineToArgvW (which is the most common way). Notable exceptions are msiexec.exe and cmd.exe (and thus, all batch files), which have a different unquoting algorithm. In these or other similar cases, you can do the quoting yourself and provide the full command line in SysProcAttr.CmdLine, leaving Args empty.
反正我看不懂,看人家的解释:
也就是说,针对 cmd 参数加的引号参数会有不同的逻辑,必须在 SysProcAttr.CmdLine 中写入原始参数了,但是 Args 留空,又会导致 SysProcAttr 值为 nil ,所以简单赋值也是不行的
改了一下代码:
cmdLine := fmt.Sprintf(`copy *"%s" "%s"`, copyPaths, targetDir)
cmd := exec.Command("TeraCopy.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: "/c " + cmdLine}
err := cmd.Start()
解决。
学习 go 一段时间,觉得它的开发者很矛盾,比如三元运算符,很多人都想要它,但官方却以语法统一、可能会导致阅读困难之类的理由推脱。 但
return r ? true : false
不比你 if 要整洁易读? 对多字节的处理也很费劲,我到现在不知道怎样查找某个中文的位置,IndexRune 报错,也没谷歌到答案
fmt.Println(strings.IndexRune("学习", "习"))
Error
./prog.go:9:42: cannot use "习" (untyped string constant) as rune value in argument to strings.IndexRune
是不是有人要说,爱用用,不用滚呢?
1
haochen2 2022-04-08 17:39:26 +08:00 3
strings.IndexRune 建议好好看看函数签名,第二个参数是 rune 类型,你给了个字符串
|
2
darrh00 2022-04-08 17:45:38 +08:00
strings.IndexRune("学习", '习')
|
3
ikaros 2022-04-08 17:46:42 +08:00
啊? 第一个问题报错 file not found 应该很好一步步排查吧; 第二个错误也说了 cannot use "习" (untyped string constant) as rune value in argument to strings.IndexRune ,而且这个是编译期的问题,编辑器就能提示出来的吧;顺带我也觉得 go 有点烂,转 rust 吧
|
4
haochen2 2022-04-08 17:47:13 +08:00
go 标准库实现的质量非常高,希望能抱着学习的心态去探索她它
|
5
keepeye 2022-04-08 17:52:29 +08:00
哈哈 你之前用的啥? java 吗?
|
6
fishCatcher 2022-04-08 17:55:56 +08:00 via iPhone 5
来跟我一个字一个字读:cannot use untyped string constant as rune value in argument
|
7
Mohanson 2022-04-08 17:57:41 +08:00 10
exec.Command 每一个 args 都要做一个参数传的, 正确写法是 `exec.Command("TeraCopy.exe", copyPaths, targetDir)`
另外真的很烦你这种人... |
8
v2kt 2022-04-08 17:58:39 +08:00
cannot use untyped string constant as rune value in argument
|
9
ck65 2022-04-08 17:59:31 +08:00
对,会有人说的。
|
10
Trim21 2022-04-08 18:04:30 +08:00 via Android
exec.Command 的 args 是直接传进去的,不需要用 fmt 再拼接一下,这地方不是 shell 还会解析你的命令行。(这个问题在其他语言其实也有类似的)
string 和 rune 不是一个东西。 |
11
sqfphoenix 2022-04-08 18:04:42 +08:00
cmd := exec.Command("notepad.exe", filepath.Join("D:/", "metrics.txt"))
使用 filepath 很难吗 使用 cmd.String()输出看看自己的命令很难吗 看一下 strings 的源码很难吗 |
12
lance6716 2022-04-08 18:14:36 +08:00 via Android
无力吐槽,再说两个
return r ? true : false 跟 return r 有什么区别? 调用 exec.Command 之前不会看一眼他的函数注释? |
13
ScepterZ 2022-04-08 18:16:46 +08:00
实习那年遇到过这个问题,后来发现是每个 args 要单独传,不能自己拼起来
最后那个,分不清字符和字符串实在不是语言的问题 |
14
CRVV 2022-04-08 18:18:54 +08:00 14
这个传参数的问题实际上是 Windows 的问题,我大概解释一下
首先,大家通常理解的参数,是一个数组。 C 语言里面会写 int main( int argc, char* argv[] ),Java 会写 public static void main(String[] args),参数都是数组。 所以 Go 的 exec.Command 是 func Command(name string, arg ...string) *Cmd 。arg 也是数组,写 Command("echo", "a", "b", "c") 就是传了 3 个参数给 echo 。 但是,Windows 里面的参数是一个字符串,也就是 Go 的文档里面说的 “On Windows, processes receive the whole command line as a single string” Windows 里面的程序在接收到这个大字符串以后,再自己把它拆成数组,得到大家通常理解的一串参数。 问题在于,Windows 不同的程序有不同的方法来拆这个字符串,所以拆出来的数组也不一样。 这里 Go 的行为是说,如果你在 Command 里传了一个数组的参数,那么 Go 就按照 Windows 通常的拆法把这些参数拼起来,但是 Windows 上的 cmd.exe 和 msiexec.exe 的拆法并不是那个通常的拆法,所以会出问题。如果你要调用的程序是 cmd.exe ,那么 Go 拼字符串的算法就是错的,请自己把字符串拼好了放到 SysProcAttr 里面。 但是楼主调用的程序不是 cmd.exe ,也就是说楼主遇到的问题根本不是这个问题。 我能看出来的问题,首先是一开始楼主少写了一个 copy ,然后是把两个参数拼到了一个参数里面,那当然不能用了。 这个问题和 Go 和 Windows 都没有关系,纯粹是楼主自己的问题。 把这个事讲完,把两个参数拼到一个参数里面的意思是 cat a b 是说把 a 和 b 两个文件的内容打出来 cat "a b" 是说有一个文件的文件名是 a 空格 b ,把这一个文件的内容打出来,如果你想要的是前一种,这样写就会报错说找不到文件 |
15
cassyfar 2022-04-08 18:21:13 +08:00
这种水平也来杠?
|
16
ChrisFreeMan 2022-04-08 18:23:55 +08:00 via iPhone
go 的话题真活跃啊,问个 swift 的问题半天没人理
|
17
thevita 2022-04-08 18:29:41 +08:00 2
比较适合些 PHP
---- 没有看不起 PHP 的意思,PHP 是最好的语言 |
18
ysc3839 2022-04-08 18:42:43 +08:00
@CRVV 补充一下,类 Unix 系统传递的参数就是字符串数组,调用方怎么传递的,接收方可以原样接收到,不需要考虑引号、转义之类的问题。
|
19
yyf1234 2022-04-08 18:47:24 +08:00 via iPhone
排错能力不太行呀兄弟
|
20
0o0O0o0O0o 2022-04-08 18:55:35 +08:00 via iPhone
我也至今没搞懂 rune ,所以会避免用…不过我明白这是因为自己菜,菜是因为自己懒不去读文档
我偶尔用 go 写一些 windows 的小工具,遇到过一些真正的坑,不过我对平台相关或是 cgo 相关的坑都比较宽容… |
21
ec0 2022-04-08 18:57:18 +08:00
fmt.Println(strings.IndexRune("学习", '习')) 为什么返回的是 3 ,我以为是 1
|
22
KaynW 2022-04-08 18:59:48 +08:00
无力吐槽...
|
24
Tink 2022-04-08 19:04:22 +08:00 via Android
真的无力吐槽
|
25
Jarvis666 2022-04-08 19:22:26 +08:00
想黑 win ,又想黑 go ,又质疑人家跨平台开发的能力,啧啧
|
26
listenerri 2022-04-08 19:43:36 +08:00 via Android 1
“属实被喷怕了”
哈哈,建议 OP 慎重开喷,毕竟己不所欲勿施于人 |
27
deplivesb 2022-04-08 19:51:05 +08:00
又菜又爱吹
|
28
skiy 2022-04-08 20:56:45 +08:00
@0o0O0o0O0o rune 是 int32 的别名,这个有什么难理解的?换个名称也一样的使用方式。
rune is an alias for int32 and is equivalent to int32 in all ways. https://github.com/golang/go/blob/5a90270d7f5b384de31399133c7336d007fbd93d/src/builtin/builtin.go#L92 |
29
0o0O0o0O0o 2022-04-08 21:28:26 +08:00 via iPhone
@skiy 是的,不难理解,猜测也是类似于别的语言里统计 UTF-8 字符数的方式,如我在#20 的自我批评,就是懒...
|
30
Vegetable 2022-04-08 21:37:07 +08:00 4
学而不思则罔,思而不学则殆。
我经常想发这句话,但是实际很少发。我觉得你很需要这句话。 |
31
hallDrawnel 2022-04-08 21:51:53 +08:00
第一个问题,把参数拆开成数组,交给基础库去完成拼接这才是跨平台的做法,你可以在 docker 、k8s 和各种 IDE 中发现都是这样输入的。
第二点是纯粹连编译错误都不看。 你要是喷在点上那肯定是大家跟着你一起喷,但这明显是你菜啊。 |
32
BeautifulSoap 2022-04-08 22:02:58 +08:00 via Android
其他不发表意见,但关于三元运算符我坚决站在 Go 这边
莫非定律了解下。只要语言给你用三元运算符,那绝对有程序员会拿它写出正常人没法轻松理解的代码。 比如每当看见 php 项目代码里有人把三元运算符玩出花的时候,我心里都是一万句草泥马 |
33
zeronofreya OP @BeautifulSoap 那 goto 有何见解?
|
34
BeautifulSoap 2022-04-08 22:42:16 +08:00
@zeronofreya ?那还用问?当然是讨厌+反对 goto 咯,还有别的可能性?(当然 Go 一些功能你不用 goto 没法实现,有时候不得不捏着鼻子用)
所以,我一碗水端平了,你现在应该对于我坚决反对三元运算符没意见了吧? |
35
skiy 2022-04-08 22:48:10 +08:00
你这知识面有点窄啊。。。
goto 是部分语言的一个特征。 C 语言的: https://www.runoob.com/cprogramming/c-goto-statement.html C++ 的: https://www.runoob.com/cplusplus/cpp-goto-statement.html C# 的: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/statements/jump-statements#the-goto-statement JAVA 虽然没有实现,但是保留了这个关键字。 |
36
BeautifulSoap 2022-04-08 22:57:07 +08:00
@zeronofreya 对了,有的东西你真要比烂的话我觉得三元运算符 100%是要比 goto 更烂的
比如 php 同时支持 goto 和三元运算符,但我 review 和参与的所有 php 项目没一个人在 php 中用过 goto ,而相应的在 php 中瞎几把乱用三元运算符的一大堆 比起 goto ,三元运算符是一个很容易让写代码的人产生迷之自信,让人有一种我写出的“简洁”代码很酷的错觉 |
37
liuzy1999 2022-04-08 23:00:57 +08:00
建议楼主加强英语能力与耐心,你会发现这些问题会改善很多的。
|
38
surbomfla 2022-04-08 23:13:08 +08:00 via Android
无论是百度还是必应 搜索 strings.IndexRune 都有正确的用法示例,op 是怎么找到 `[]rune(str)` 这种用法的?
|
39
Tink 2022-04-09 02:45:20 +08:00 via Android
你这个排错和搜索能力还需要提高
|
40
singerll 2022-04-09 06:04:36 +08:00 via Android
不是针对 go ,三元运算符你说易读我真的不认同。
还有第一个问题,本人非专业开发运维人员,偶尔写点小脚本,我用 python 的 subprocess 模块也有这个问题,第一次用也是调了好久,说白了就是懒得扒拉官方文档,随便搜个教程开始写,最后出问题排除就是比较麻烦。。。 |
41
xuanbg 2022-04-09 06:32:42 +08:00
@BeautifulSoap 连 Java 这种古板的语言都支持三元呢。。。
|
42
holulu 2022-04-09 06:52:04 +08:00
你摘的英文文章说得挺详细的。
|
43
yulon 2022-04-09 06:58:53 +08:00
为啥要用格式化组合参数啊,那么喜欢用格式化来写 C 吧。
Go 天生支持 Rune ,Windows 下还自动给你转码 Unicode ,居然说多语言不好处理,那来试试 C++ 吧。 怎么三元又能出来鞭尸一顿,那来写 C/C++ 啊,C 系的语法全都有吧。 什么爱用用咬不咬人,C++ 用好了绝对比用 Go 要爽。 所以快来写 C++ 啊!所以快来写 C++ 啊!所以快来写 C++ 啊! 你为什么还不来万能的 C++ 呢? |
44
zjyl1994 2022-04-09 09:44:41 +08:00 via iPhone
天,大佬你学学英文吧,实在不行装个词典软件,编译器说的很明白了。这都不想弄,要不试试中文编程?
|
45
tomolo 2022-04-09 09:51:12 +08:00
所以程序员还是需要学一点英语的
|
46
whileFalse 2022-04-09 09:55:21 +08:00 via iPhone
反正是有那种在三元里面套三元的傻*,比如我。
怎么说呢,我是运维但写了二十年代码,看别的运维的代码都是平趟,别人看我代码那就祝你好运吧,要是哪天不高兴写了个复杂的表达式就够你研究一会的,但对于我来说看懂类似的表达式跟看明白注释用时没啥区别。 所以,go 不让你用这种 c 遗留下来的语法是为你好啊孩子,我们这种老油条真的无所谓的。 |
47
carlclone 2022-04-09 10:12:41 +08:00
不如先找找自己水平问题再甩锅?
|
48
adoal 2022-04-09 10:13:26 +08:00 via iPhone
连三元运算符都能吵起来,那 if expression 你们是不是要当魔鬼了
|
49
fauieh32fihe 2022-04-09 10:41:45 +08:00
这种货色。。。哈哈
|
51
yin1999 2022-04-09 12:45:42 +08:00
我真的是无语了,错误提示真有那么难看懂吗,strings.IndexRune 这个函数的第一个参数用的字符串,第二个参数用 rune ,要调用也应该是些 strings.IndexRune("学习", '习') 这么写,也就是 2 楼给出的答案,咋还能写成 strings.IndexRune([]rune("学习"), xxxx) 这样的呢(看你回复里面给出的错误提示都知道你的第一个参数填的啥了,这还不够明白吗)
|
52
mengzhuo 2022-04-09 13:48:32 +08:00
额,感觉还是没仔细看错误提示……
这样都能喷,来看看 Rust ,保证你一下午都编译不出来:) |
53
rekulas 2022-04-09 14:17:23 +08:00
TeraCopy - Error
错误已经很明显了,被调用程序报的错,这都能怪到 go 的头上,你自己都乱喷就别怪别人喷你了 首先确保你参数正确,尽量用 git bash 调试好正确参数,然后复制到代码里基本就可用-少数可能需要微调 ("TeraCopy.exe", "copy", `*"e:\1.txt"`, `"e:\a\"`) 没用过 tera ,不知道*"e:\1.txt" 为什么要这样写,但是双引号里可能需要转义才对,例如 e:\\1.txt `"e:\a\"` ,这种写法 我觉得就是错误的,直接`e:\a\` 说不定还可以 如果双引号是程序必须的参数,可以试试 "copy", `*"e:\\1.txt"` `e:\a\` 你最好发一遍可以正确执行的命令,大家可以帮你看看 最后再重申这跟 golang 无关,你用其他语言也可能遇到一样的问题 |
54
gam2046 2022-04-09 15:19:48 +08:00
@singerll #40 大佬 我也是近期新学的 golang ,但是可能受其他语言影响,golang 设计的异常判断
if _, err := something; err == nil {...} 就是这种是标准的处理方法嘛?总感觉写起来怪怪的。 |
55
GeruzoniAnsasu 2022-04-09 15:26:10 +08:00
|
56
gam2046 2022-04-09 15:56:19 +08:00
@GeruzoniAnsasu #55 唔,好吧。就是我比较不能适应的是这种写法
if _,err:= ... ; err != nil{ ... } 一个方法中有好多 if err != nil ,相比其他语言的 try catch ,一些兜底的错误处理,可以统一放在 catch 里。 我也不太明白是我理解不透彻嘛 |
57
whyso 2022-04-09 17:46:02 +08:00
说实话,这种错误我都不好意思贴出来给大家看。。。
|
59
lysS 2022-04-09 19:10:54 +08:00
还有三目,估计楼主没有写过业务。常用的三目大概长这样
const word = (res.distance === 0) ? 'a' : (res.distance === 1 && res.difference > 3) ? 'b' : (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c' : 'd'; |
60
fyibmsd 2022-04-09 19:32:18 +08:00
一个都没黑到点子上
|
61
actar 2022-04-09 21:29:49 +08:00
const TeraCopy = "D:\\TeraCopy\\TeraCopy.exe"
func main() { copyPaths := os.Args[1] targetDir := os.Args[2] command := exec.Command(TeraCopy, "copy", fmt.Sprintf("*%s", copyPaths), targetDir) if err := command.Run(); err != nil { panic(err) } } 可以这样写,亲测可行 TeraCopy.exe copy *"G:\1 source.txt" "G:\target\" 等价于 TeraCopy.exe copy "*G:\1 source.txt" "G:\target\" exec.Command 传递参数的时候,不需要引号括起来 |
62
actar 2022-04-09 21:32:54 +08:00
终端环境的参数两边的引号,是由终端进行处理的。传递进程序,是不带两边的引号的
|
63
KousukeSakurako 2022-04-09 23:54:29 +08:00 via iPhone
怎么回事,黑不到点子上啊我看着都急
|
64
kkbblzq 2022-04-10 07:56:48 +08:00
说实话,前半段看下来还好,但是你加了后半段,看起来就很尴尬了,因为非常明显的报错😂,感觉这不是 go 不 go 的问题了,换个语言报错你确定你能看得出来?
|
65
borpubi 2022-04-12 16:37:12 +08:00
对于一个伪 IT 来说,三元运算符确实没有 if 易读易懂好解释。
|