有人用 goto 语句么?我是用它代替递归

2017-10-24 16:35:17 +08:00
 me15000

//递归
void repeat(c) {

	
		//需要重复的代码
	

		if (xx) {
			 repeat(xx);
		}

}

//goto 代替递归
void repeat(c) {

	loop:
		//需要重复的代码
	

		if (xx) {
			goto loop;
		}

}


        //一个采集程序
        public void Run(string listurl)
        {
            using (var wc = new WebClient())
            {
                loop:

                string html = Encoding.GetEncoding("utf-8").GetString(wc.DownloadData(listurl));
                var doc = new HtmlDocument();
                doc.LoadHtml(html);
                var nodes = doc.DocumentNode.SelectNodes("//ul[@id=\"data_list\"]/li/div/a");
                for (int i = 0; i < nodes.Count; i++)
                {
                    var node = nodes[i];
                    string link = "http://www..cn" + node.Attributes["href"].Value;
                    string title = node.SelectSingleNode("span[@class=\"sTit\"]").InnerText;
                    Save(title, link);
                }
                var nextnode = doc.DocumentNode.SelectSingleNode("//div[@class='page mb clearfixs']/em/following-sibling::a");
                if (nextnode != null)
                {
                    listurl = "http://www..cn" + nextnode.Attributes["href"].Value;
                    goto loop;
                }
            }
        }
10890 次点击
所在节点    分享发现
128 条回复
JamesMackerel
2017-10-24 19:12:19 +08:00
另外,我想在编写生产环境的代码时,如果遇到尾递归,我认为我宁可把它优化为循环,或者就写一个尾递归,便于理解。
whileFalse
2017-10-24 19:53:17 +08:00
我在知道 for 之前用过一段 goto。
后来知道了 for,觉得不如 goto 好用。

那年我 14 岁。
tnx2014
2017-10-24 19:56:22 +08:00
用 goto 本身没什么问题,但是还是不推荐大面积的使用,更何况你也知道你这种结构就相当于循环,只有写汇编这种东西没办法不用的时候才使用,你现在觉得轻松是因为你只用那么一次,放弃循环语句,goto 满天飞试试看,你就知道多痛苦了,因为 goto 只能指示入口,其实还是从上往下顺序执行,有多个语句块时,有时候代码都不知道往哪儿写。

推荐一个游戏,Human Resource Machine,用类汇编语言来实现相应的要求,楼主可以感受一下里面要求优化代码的痛苦。
northisland
2017-10-24 20:01:07 +08:00
邪教!
geelaw
2017-10-24 20:24:15 +08:00
那个……您应该写成尾递归,聪明的编译器会直接优化成跳转。

现在两份代码有明显区别,是因为递归调用结束之后还要 Dispose,外加递归版本会创建 没有必要多 个 WebClient。
longaiwp
2017-10-24 21:33:24 +08:00
@geelaw 显然 C#是不自带尾递归优化的,当然你用 R#可以实现手动尾递归优化,至于为什么 C#不带,我猜是做了有什么问题(微笑
geelaw
2017-10-24 21:56:20 +08:00
@longaiwp 这段代码谈不上尾递归优化,因为那个递归并不是尾递归。

不存在“ C# 没有尾递归优化”这种说法,因为理论上尾递归优化也可以发生在 JIT 的时候,而 JIT 并不知道这段代码是 C# 还是别的编译过来的。我不知道现在的 JIT 是否有这种优化。
fox0001
2017-10-25 01:19:23 +08:00
你高兴就好…
cnTangLang
2017-10-25 06:30:57 +08:00
如果代码是你自己去维护,你用 goto 没有问题。如果不是,尽量不要用。我的开发规范中,是严禁使用 goto 的。
introom
2017-10-25 08:30:20 +08:00
楼主没有放弃用 goto 是好事情,很多人都是教条不敢用。不过,说实话楼主贴的代码让编译器 tco 或者用循环更直接。
htfy96
2017-10-25 08:50:40 +08:00
业务逻辑代码尽量避免出现 goto
backward goto 依旧是大忌,ng/linux 的 goto fail/cleanup 基本都是 forward 的,对控制流影响较小
过早的优化是万恶之源

所以总体不推荐这么搞,特别是.net
ZhLTE
2017-10-25 09:03:33 +08:00
不建议 goto 破坏阅读体验
exch4nge
2017-10-25 09:19:18 +08:00
看标题,再看代码有点蒙... 标题要是用 goto 代替了循环,估计大部分人都能理解...

首先 ,goto(LZ 用的方式),for,while,do while 其实编译后基本都一样;结构化编程开始流行后,有人提出来 goto(LZ 用的方式)都可以用后面几个方式替代,后面循环语句更有助于代码阅读,所以基本上 goto(LZ 用的方式)不怎么这么用了。

不过 goto 在错误处理等等地方上比较好用,用在这方面倒是没啥太大问题。

其次,递归代码都可以写成非递归的形式(模拟个栈,需要写循环语句),LZ 写的这种又是尾递归,尾递归更容易写成非递归,可以不用栈,直接用循环语句就能写。显然,也可以反着来,所有循环语句也可以写成递归形式,不过编译器如果没优化尾递归会爆栈罢了。

所以,可以说,goto(LZ 用的方式),循环语句,尾递归方式原理上都一样,不过一般为了代码阅读性,使用循环语句是相对来说比较好的选择,而且一般人都会优先使用循环语句。(学院派 Lisp 里习惯用递归)
linxl
2017-10-25 09:44:25 +08:00
大多数脚本语言都没有尾递归优化
airqj
2017-10-25 09:46:31 +08:00
不考虑使用场景的使用都是耍流氓
noli
2017-10-25 10:27:51 +08:00
用递归有栈溢出的风险,这是事实。
但这不是使用 goto 的理由。
没有什么使用 goto 的场合是找不到不用 goto 的替代方式的。而使用 goto,在很多原生语言例如 c++里,因为打破了符号作用域,会产生意外的效果。如果不是这些原生语言,那么 goto 比起正常使用其替代方式,带来的运行效率提升基本等于无。

所以我不知道楼主有什么好感到得意的,我看到的只有无知。
longaiwp
2017-10-25 10:32:47 +08:00
@geelaw 不是完全没有,但是起码编译器是不会做的,至于 CLR 不一定会做
geelaw
2017-10-25 10:51:49 +08:00
@noli goto 和作用域的关系是啥?
msg7086
2017-10-25 11:08:33 +08:00
把递归重写成手工维护堆栈 /队列的循环是一个程序员的基本能力。
比如说你楼顶附言里贴的这 3 段代码。
如果我今天是码农职位面试官,我要你写一个这样的程序,你给我这 3 段里的任何一段,对我来说都是不合格的。

因为你连 DFS/BFS 的基本写法都不知道。
如果你不是科班毕业的,那我不怪你。
如果你正常读完了计算机本科,写不出 DFS/BFS 应该的写法,那还是回去重新读一下大学课程比较好,特别是基础算法课。
sgissb1
2017-10-25 11:23:00 +08:00
说实话,开源代码里面用 goto 的最多。

但是,goto 用的溜的,也不影响代码阅读和维护。但就目前来说大部分代码还是给人非常混乱的阅读理解和维护性。
goto 能不用就不要用,除非高开源代码,有潜在可以甩手不管的机会,否则要自食其果的。

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

https://tanronggui.xyz/t/400286

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

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

© 2021 V2EX