ruby是一門動態指令碼語言,這個大家都知道。
我今天想討論的問題是ruby中的異常處理機制,首先貼一段代碼:
1 class SocketError < StandardError
2 end
3
4 class Test
5 @host = "192.168.0.1"
6 @port = 8000
7 def opensocket
8 ret_str = "socket open Fail"
9 begin
10 socket = TCPSocket.open(@host,@port)
11 ret_str = "socket open successed!"
12 rescue => e
13 puts "socket error"
14 raise SocketError
15 end
16 return ret_str
17 end
18 end
19
20 #############################
21 t = Test.new
22 begin
23 str = t.opensocket()
24 puts str
25 rescue SocketError
26 puts "socket open fail in opensocket method"
27 end
28 #############################
這段代碼列印的結果大家都應該會知道:
socket error
socket open fail in opensocket method
在看下下面的這段代碼
1 class SocketError < StandardError
2 end
3
4 class Test
5 @host = "192.168.0.1"
6 @port = 8000
7 def opensocket
8 ret_str = "socket open Fail"
9 begin
10 socket = TCPSocket.open(@host,@port)
11 ret_str = "socket open successed!"
12 rescue => e
13 puts "socket error"
14 raise SocketError
15 ensure
16 return ret_str
17 end
18 end
19 end
20
21 #############################
22 t = Test.new
23 begin
24 str = t.opensocket()
25 puts str
26 rescue SocketError
27 puts "socket open fail in opensocket method"
28 end
29 #############################
30
31
大家說這段代碼返回的是什嗎?
還是和上面的代碼返回的結果一致嗎?
結果是:
socket error
socket open Fail
大家可能想“為什麼他能返回的結果是:socket open Fail ,在在外層的resure中為什麼不能接收到異常呢?為什麼不能列印 socket open fail in opensocket method“
今天要討論的問題就是這個。
在第二段代碼與第一段代碼的不同就是:return 語句放置 的位置不同。在第二段代碼中吧return 放在 ensure中 ,第一段代碼則是放置在 begin ... end語言之後。
其實就是這點的原因導致了上面的結果。在程式碼片段2中,我們只是在是希望在異常的善後處理中能把我們想要的值返回去。
這樣做將導致一個結果就是,在之前的rescue中raise 的異常將因為這個return而被”吃“掉。 也就是說,這個時候的他就不把raise 這個異常往上拋了,自己處理了,
其實在強型別語言裡是不允許在ensure中return的。
例如在C#語言中,在try...catch...finally 的 finally中是不允許有return的,這樣就避免了這樣的問題發生。