`
cloudtech
  • 浏览: 4606183 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

说说Erlang的异常处理

 
阅读更多

转载请注明,来自:http://blog.csdn.net/skyman_2001

Erlang的异常处理一般是try catch,虽然erlang比较推荐Let It Crash,不怎么推荐防御式编程,但try catch在以下两个方面还是很有用的:

1. 处理用户输入,因为你不能确保输入的数据的正确性,这时为了稳定性,可以使用try catch(比如网游服务器,稳定性是很重要的);

2. 嵌套很多层的函数,如果通过一层一层的返回返回值写起来比较麻烦,这个时候可以使用try catch,里面的函数可以通过throw来返回到顶层函数。网游中的一个典型的例子就是某个操作的条件检查(比如学习技能、使用物品),会有很多条件,用throw的方法会使代码简练很多。erlang自己库里也有这样的例子,比如ssl库:

new_connect(Address, Port, Options, Timeout) when is_list(Options) ->
    try handle_options(Options, client) of
	{ok, Config} ->
	    do_new_connect(Address,Port,Config,Timeout)
    catch 
	throw:Error ->
	    Error
    end.

handle_options(Opts0, _Role) ->
    ...
    VerifyNoneFun = handle_option(verify_fun, Opts, DefaultVerifyNoneFun),

    UserFailIfNoPeerCert = handle_option(fail_if_no_peer_cert, Opts, false),
    UserVerifyFun = handle_option(verify_fun, Opts, undefined),
    CaCerts = handle_option(cacerts, Opts, undefined),

    {Verify, FailIfNoPeerCert, CaCertDefault, VerifyFun} =
	%% Handle 0, 1, 2 for backwards compatibility
	case proplists:get_value(verify, Opts, verify_none) of
	    0 ->
		{verify_none, false,
		 ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun};
	    1  ->
		{verify_peer, false,
		 ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
	    2 ->
		{verify_peer, true,
		 ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
	    verify_none ->
		{verify_none, false,
		 ca_cert_default(verify_none, VerifyNoneFun, CaCerts), VerifyNoneFun};
	    verify_peer ->
		{verify_peer, UserFailIfNoPeerCert,
		 ca_cert_default(verify_peer, UserVerifyFun, CaCerts), UserVerifyFun};
	    Value ->
		throw({error, {eoptions, {verify, Value}}})
	end,
    ...
    {ok, ...}.

handle_option(OptionName, Opts, Default) ->
    validate_option(OptionName, 
		    proplists:get_value(OptionName, Opts, Default)).

validate_option(ciphers, Value)  when is_list(Value) ->
    Version = ssl_record:highest_protocol_version([]),
    try cipher_suites(Version, Value)
    catch
	exit:_ ->
	    throw({error, {eoptions, {ciphers, Value}}});
	error:_->
	    throw({error, {eoptions, {ciphers, Value}}})
    end;
...

从上面代码可以发现,在顶层函数里有try catch,如果是正确的就做进一步处理,如果catch到throw异常,则返回该异常信息(注意这里用throw:Error表示只处理throw异常,因为嵌套函数里的错误的返回是通过throw/1来抛出的),嵌套函数如果有错就直接throw/1,这样就省去一层一层返回返回值的麻烦了。

关于异常处理的一个通常做法是:在捕获到异常时将异常信息写到日志中,方便程序的分析和修复。异常和日志都是保证软件产品质量的重要手段!

还有一个要注意的点是:try块是不能构成尾递归的,erlang虚拟机必须始终保持它的引用,以防异常出现,所以如果在try块调用递归函数会造成大量内存消耗。


参考文献:
Errors and Exceptions:http://learnyousomeerlang.com/errors-and-exceptions


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics