在CMD中使用GOTO的缺点

在CMD中使用GOTO的缺点,cmd,goto,Cmd,Goto,我完全了解关于使用GOTO()是否是良好实践的永恒讨论,我想问的是,使用GOTO,特别是在CMD/dosshell中,是否有一些缺点 所谓缺点,我的意思是,如果出现性能损失或大量使用GOTO可能会终止我的脚本的情况(如后面描述的行为)。我知道,因为TI-BASIC没有它就无法创建结构化程序,因此在该平台上重复使用GOTO最终会耗尽内存。以下引用解释了此行为: 使用Goto退出任何需要End命令的代码块会导致内存泄漏,在程序完成运行或执行Return命令之前,内存泄漏将不可用,并且会降低程序的速度

我完全了解关于使用GOTO()是否是良好实践的永恒讨论,我想问的是,使用GOTO,特别是在CMD/dosshell中,是否有一些缺点

所谓缺点,我的意思是,如果出现性能损失或大量使用GOTO可能会终止我的脚本的情况(如后面描述的行为)。我知道,因为TI-BASIC没有它就无法创建结构化程序,因此在该平台上重复使用GOTO最终会耗尽内存。以下引用解释了此行为:

使用Goto退出任何需要End命令的代码块会导致内存泄漏,在程序完成运行或执行Return命令之前,内存泄漏将不可用,并且会降低程序的速度


CMD中循环执行命令的另一种“方式”是FOR语句,对于预期参数非常具体,因此不能在任何情况下使用。

GOTO:label
是批处理编码的一个组成部分,没有内置的缺点-它是批处理脚本的一个必要部分。

GOTO:label
是批处理编码的一个组成部分,没有内置的缺点-它是批处理脚本的必要组成部分。

在Windows批处理脚本中使用GOTO通常是安全的,有时也是必要的。但有三个非直观的设计特征值得注意:

1)不要转到放在括号内的代码块中的标签

您可以转到放置在括号内的块中的标签,但它可能不会给出您想要的结果。例如,For循环DO块中的GOTO将立即终止循环。如果GOTO引用DO块中的标签,控制将正确地传输到标签位置,但是批处理解析器现在对FOR循环上下文一无所知。代码将像不在循环中一样执行。有关更多信息,请参阅的已接受答案

2)标签的位置会影响性能。

这通常不是一个问题,除非您处理的是一个非常大的脚本

执行
GOTO:label
(或
CALL:label
)时,批处理程序开始从当前脚本位置扫描,查找第一个出现的
:label
。如果它到达文件的末尾而没有找到标签,那么它将返回顶部并继续搜索。如果到达起点时未找到标签,则会引发错误。因此,在非常大的脚本中,有时可以通过构造脚本,使标签在它们各自的GOTO(或调用)后不久出现,从而提高性能。当然,如果标签是从多个位置引用的,这可能是不可能的

3)同一标签实际上可以在多个位置安全使用(不建议使用)

一旦您了解了上面第2点中描述的标签扫描过程,如果您小心,就可以安全地重新使用标签

例如,以下脚本将正常工作:

@echo off

for %%A in (1 2 3 X Y Z) do (
  echo %%A
  if %%A equ 3 goto break
)
:break

for %%A in (A B C 8 9 10) do (
  echo %%A
  if %%A equ C goto break
)
:break
--输出--


尽管重新使用标签是可行的,但这不是一个好的做法,因为它可能会混淆试图解释或调试脚本的任何其他人。

在Windows批处理脚本中进行转到通常是安全的,有时是必要的。但有三个非直观的设计特征值得注意:

1)不要转到放在括号内的代码块中的标签

您可以转到放置在括号内的块中的标签,但它可能不会给出您想要的结果。例如,For循环DO块中的GOTO将立即终止循环。如果GOTO引用DO块中的标签,控制将正确地传输到标签位置,但是批处理解析器现在对FOR循环上下文一无所知。代码将像不在循环中一样执行。有关更多信息,请参阅的已接受答案

2)标签的位置会影响性能。

这通常不是一个问题,除非您处理的是一个非常大的脚本

执行
GOTO:label
(或
CALL:label
)时,批处理程序开始从当前脚本位置扫描,查找第一个出现的
:label
。如果它到达文件的末尾而没有找到标签,那么它将返回顶部并继续搜索。如果到达起点时未找到标签,则会引发错误。因此,在非常大的脚本中,有时可以通过构造脚本,使标签在它们各自的GOTO(或调用)后不久出现,从而提高性能。当然,如果标签是从多个位置引用的,这可能是不可能的

3)同一标签实际上可以在多个位置安全使用(不建议使用)

一旦您了解了上面第2点中描述的标签扫描过程,如果您小心,就可以安全地重新使用标签

例如,以下脚本将正常工作:

@echo off

for %%A in (1 2 3 X Y Z) do (
  echo %%A
  if %%A equ 3 goto break
)
:break

for %%A in (A B C 8 9 10) do (
  echo %%A
  if %%A equ C goto break
)
:break
--输出--


尽管重复使用标签是可行的,但这并不是一个好的做法,因为它可能会使试图解释或调试脚本的其他人感到困惑。

“每次使用一个GOTO时,有关上一个GOTO的信息都存储在内存中”——什么?我对TI-BASIC一无所知,但我知道没有一个类似GOTO的设施做过类似的事情,我无法设想一个用例,它会严重破坏编程平台,所以我想澄清一下,并了解一些信息来源。我99.9%肯定你在TI-BASIC中将
GOTO
GOSUB
混淆了。至少在我遇到的每一种微机BASIC中,
GOTO
都不存储它的来源,事实上在其他任何编程语言中都不存储它。@delnan from:使用GOTO退出任何需要