@
cloudzhou switch case 和 exception 的作用肯定不一样啊。
1. 如果 SocketException 的各种 ErrorCode 都以 SocketException 的子类出现,要么我用 SocketException 一个 catch 把各种子类全部捕获了,在这种情况下,你才需要根据子类细分再手动 switch case 来处理 —— 这时候很有可能会漏掉某种子类,这个弊病跟用返回值处理是一样的
2. 然而你也可以 catch 每一个 SocketException 的子类,这样就是编译器替你做了 switch case
这种情况下你一样可以针对细分情况分别做处理:
再然后
2.1 如果我的疏漏了 SocketException 的子类没有捕捉,并且也没有 catch SocketException 的本尊,那么,会 crash
2.2 如果我最后有捕捉 SocketException 本尊,甚至直接 catch Exception (所有 Exception 的共同父类),那么尽管我依然遗漏了情况没有处理,但是因为 catch 了, exception 发生后的代码就不会被执行了,程序不会 crash 并且后续的代码不会意外地使用了无效的返回值。
也就是说,像 golang 里面这样的错误, 也是 @
goool 代码里面的问题:
func send_data(n int, target string, content string, result chan Pair) {
conn, err := net.DialTimeout("tcp", target, time.Duration(1 * time.Second))
if err != nil {
result <- Pair{n, err}
return
}
defer conn.Close()
DialTimeout 的作者不必在异常发生时硬要给 conn 塞一个值,
而调用 DialTimeout 的时候也不必防御性地 return
要一遍又一遍地重复写这些 resut <-Pair{n, err} return 这种代码,我真的不能认为它 DRY
再况且,我本来出这个题目,就是要考验 golang 处理错误的能力。
他的代码根本就无视了这一部分的逻辑,你看起来当然简洁易懂咯。
实际上,就以这段为例,至少要检查一下 err 的具体情况,才能决定 Pair 是不是应该送出去。
这时候你就会发现谁的代码里面到处都是 switch case 了
再看看 抛异常的方案, send_x_target 的主要逻辑 就这几行:
var client = new TcpClient();
await client.ConnectAsync(endpoint.Address, endpoint.Port);
var stream = client.GetStream();
await stream.WriteAsync(content, 0, content.Length);
var reply = new byte[1024];
var respLength = await stream.ReadAsync(reply, 0, reply.Length);
两个版本里面都没有变过
你觉得“ Golang 显然容易理解多了”
我只能说你的口味和我的太不一样了