被 golang 坑了一下午, win 平台无法正常调用外部程序看这里。

2022-04-08 17:33:43 +08:00
 zeronofreya

很简单的调用:

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

是不是有人要说,爱用用,不用滚呢?

6449 次点击
所在节点    程序员
65 条回复
xuanbg
2022-04-09 06:32:42 +08:00
@BeautifulSoap 连 Java 这种古板的语言都支持三元呢。。。
holulu
2022-04-09 06:52:04 +08:00
你摘的英文文章说得挺详细的。
yulon
2022-04-09 06:58:53 +08:00
为啥要用格式化组合参数啊,那么喜欢用格式化来写 C 吧。

Go 天生支持 Rune ,Windows 下还自动给你转码 Unicode ,居然说多语言不好处理,那来试试 C++ 吧。

怎么三元又能出来鞭尸一顿,那来写 C/C++ 啊,C 系的语法全都有吧。

什么爱用用咬不咬人,C++ 用好了绝对比用 Go 要爽。

所以快来写 C++ 啊!所以快来写 C++ 啊!所以快来写 C++ 啊!

你为什么还不来万能的 C++ 呢?
zjyl1994
2022-04-09 09:44:41 +08:00
天,大佬你学学英文吧,实在不行装个词典软件,编译器说的很明白了。这都不想弄,要不试试中文编程?
tomolo
2022-04-09 09:51:12 +08:00
所以程序员还是需要学一点英语的
whileFalse
2022-04-09 09:55:21 +08:00
反正是有那种在三元里面套三元的傻*,比如我。
怎么说呢,我是运维但写了二十年代码,看别的运维的代码都是平趟,别人看我代码那就祝你好运吧,要是哪天不高兴写了个复杂的表达式就够你研究一会的,但对于我来说看懂类似的表达式跟看明白注释用时没啥区别。
所以,go 不让你用这种 c 遗留下来的语法是为你好啊孩子,我们这种老油条真的无所谓的。
carlclone
2022-04-09 10:12:41 +08:00
不如先找找自己水平问题再甩锅?
adoal
2022-04-09 10:13:26 +08:00
连三元运算符都能吵起来,那 if expression 你们是不是要当魔鬼了
fauieh32fihe
2022-04-09 10:41:45 +08:00
这种货色。。。哈哈
debuginn
2022-04-09 12:25:29 +08:00
@haochen2 认同。go 的标准库就是一股清流
yin1999
2022-04-09 12:45:42 +08:00
我真的是无语了,错误提示真有那么难看懂吗,strings.IndexRune 这个函数的第一个参数用的字符串,第二个参数用 rune ,要调用也应该是些 strings.IndexRune("学习", '习') 这么写,也就是 2 楼给出的答案,咋还能写成 strings.IndexRune([]rune("学习"), xxxx) 这样的呢(看你回复里面给出的错误提示都知道你的第一个参数填的啥了,这还不够明白吗)
mengzhuo
2022-04-09 13:48:32 +08:00
额,感觉还是没仔细看错误提示……

这样都能喷,来看看 Rust ,保证你一下午都编译不出来:)
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 无关,你用其他语言也可能遇到一样的问题
gam2046
2022-04-09 15:19:48 +08:00
@singerll #40 大佬 我也是近期新学的 golang ,但是可能受其他语言影响,golang 设计的异常判断

if _, err := something; err == nil {...}

就是这种是标准的处理方法嘛?总感觉写起来怪怪的。
GeruzoniAnsasu
2022-04-09 15:26:10 +08:00
@gam2046 golang 没有 exception ,没有「异常」。

它只有「错误码」

而且错误码是个字符串 hhhhh
gam2046
2022-04-09 15:56:19 +08:00
@GeruzoniAnsasu #55 唔,好吧。就是我比较不能适应的是这种写法

if _,err:= ... ; err != nil{ ... }

一个方法中有好多 if err != nil ,相比其他语言的 try catch ,一些兜底的错误处理,可以统一放在 catch 里。

我也不太明白是我理解不透彻嘛
whyso
2022-04-09 17:46:02 +08:00
说实话,这种错误我都不好意思贴出来给大家看。。。
lysS
2022-04-09 19:09:04 +08:00
@gam2046 try catch 其实就是 panic + recover
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';
fyibmsd
2022-04-09 19:32:18 +08:00
一个都没黑到点子上

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/845764

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX