文章目录

前言

有时候看不懂代码,可以直接去debug一些模块,写一些单元测试。虽然Erlang提供了专门的单元测试方法,但由于没有整体配置(暂时不想二次开发),有一些模块无法启动,所以干脆只把需要的代码拷贝出来做debug观察数据,从而理解原理。整个分析基于EMQ2.3.11。

一、调试方法

1、准备好一个空Erlang工程

参考《EMQ源码分析(一):在Windows上用IDEA搭建Erlang编译平台》,构建一个Helloworld就好。

2、拷贝代码

将需要测试的部分代码从EMQ里面拷贝出来,例如我想要了解订阅树如何构建的,就需要了解Topic如何被切分成三元组的,三元组具体的数据又是怎样的,把emqttd_trie、emqttd_topic相关代码拷贝出来:

-module(hello).
-author("BEWINDOWEB").
-import(lists, [reverse/1]).

%% API
-type(word()   :: '' | '+' | '#' | binary()).
-type(words()  :: list(word())).
-type(triple() :: {root | binary(), word(), binary()}).
-type(topic() :: binary()).

-export([start/0]).


-spec(triples(topic()) -> list(triple())).
triples(Topic) when is_binary(Topic) ->
  triples(words(Topic), root, []).

triples([], _Parent, Acc) ->
  reverse(Acc);

triples([W|Words], Parent, Acc) ->
  Node = join(Parent, W),
  triples(Words, Node, [{Parent, W, Node}|Acc]).

%% @doc Split Topic Path to Words
-spec(words(topic()) -> words()).
words(Topic) when is_binary(Topic) ->
  [word(W) || W <- binary:split(Topic, <<"/">>, [global])].

word(<<>>)    -> '';
word(<<"+">>) -> '+';
word(<<"#">>) -> '#';
word(Bin)     -> Bin.

join(root, W) ->
  bin(W);
join(Parent, W) ->
  <<(bin(Parent))/binary, $/, (bin(W))/binary>>.
bin('')  -> <<>>;
bin('+') -> <<"+">>;
bin('#') -> <<"#">>;
bin(B) when is_binary(B) -> B.




start() ->
  io:fwrite("Hello, world!\n"),
  Triples = triples(<<"a/b/c">>),
  Triples2 = triples(<<"a/+/c">>).

3、断点调试

打上断点调试,就能得到自己想看的数据,从而理解原理:

二、控制台格式化输出

有时候debug的数据不正确(比如位串会以有符号8位来显示),这时需要fwrite,和printf类似。

fwrite可以类似printf去简单控制输出格式,标准格式如下:

~F.P.PadModC

1、不带参数示例

io:fwrite("123").

2、格式化参数示例

% io:fwrite("~F.P.C",data).
io:fwrite("|~10.5s|~n|",[<<"aaa">>]).
% |     aaa  |
% |
  • ~类似%;
  • F:输出长度,10代表总共10位;
  • P:输出精度,5代表a有5位;
  • C:输出格式,s代表字符串输出,n代表换行符;
  • <<"aaa">>是<<$a,$a,$a>>的语法糖;
  • 其余字符按正常字符输出。

所以最后的第一行包含了"|"+5个空格+3个a+2个空格+"|",第二行只有"|"。

3、格式化参数的含义

符号C 含义 P参数
 ~c ascii码 最大长度
重复次数
 ~f 浮点数 最大长度
精度
 ~e 科学计数法 最大长度精度
 ~n 换行符 最大次数重复次数
 ~s 字符串 最大长度
截取长度
 ~w 任意元 最大长度
字串长度
 ~W ~w、限制打印深度 最大长度
字串长度深度
 ~p 任意元、适当换行和缩进、列表输出为字串 单行/多行
缩进长度
 ~P ~p、限制打印深度 单行/多行
缩进长度深度
 ~b 进制整数(小写字母)
 最大长度
进制
 ~B 进制整数(大写字母) 最大长度
进制
 ~x 带任意前缀进制整数(小写字母) 最大长度
进制前缀
 ~X 带任意前缀进制整数(大写字母) 最大长度
进制前缀
 ~+ 带进制前缀整数(小写字母) 最大长度
进制
 ~# 带进制前缀整数(大写字母) 最大长度
进制


4、格式化参数上下界的意义

符号C 小于最大长度F超过最大长度F小于精度P超过精度P
 ~c 左侧补空格报错右侧补空格截断
 ~f 左侧补空格输出*小数点后补0小数点后截断
 ~e

 左侧补空格

输出*小数点后补0小数点后截断
 ~n (最大次数)(最大次数)  
(重复次数)  
(重复次数)  
 ~s 左侧补空格报错右侧补空格从头部开始截断
 ~w 左侧补空格输出*-输出*
 ~W 左侧补空格输出*-输出*
 ~p (0单行/1多行)(0单行/1多行)  
(缩进长度)(缩进长度)  
 ~P (0单行/1多行)  (0单行/1多行)   
(缩进长度)(缩进长度) 
 ~b 左侧补空格输出*(进制)(进制)
 ~B 左侧补空格

输出*

(进制)(进制)
 ~x 左侧补空格输出*  
(进制)(进制)
 ~X 左侧补空格输出*  
(进制)(进制)
 ~+ 左侧补空格

输出*  

(进制)(进制)
 ~# 左侧补空格

输出*  

(进制)(进制)

5、格式化参数实例

start() ->
  io:fwrite("[c]~10.3c~n",[$a]),
  % [c]       aaa
  io:fwrite("[f]~10.1f~n",[1.23]),
  % [f]       1.2
  io:fwrite("[e]~10.2e~n",[1.23]),
  % [e]    1.2e+0
  io:fwrite("[n]~2.9n"),
  % [n]
  % 
  io:fwrite("[s]~10.3s~n",["aaabbbbbbb"]),
  % [s]       aaa
  io:fwrite("[w]~60.90w~n",[{"1231231231","aaaaaa"}]),
  % [w]       {[49,50,51,49,50,51,49,50,51,49],[97,97,97,97,97,97]}
  io:fwrite("[W]~60.30W~n",[{"1231231231","aaaaaa"},5]),
  % [W]                                {[49,50,51|...],[97,97|...]}
  io:fwrite("[p]~3.0p~n",[{"123123","123123","aaaa"}]),
  % [p]{"123123",
  % "123123",
  % "aaaa"}
  io:fwrite("[P]~1.20P~n",[{"123123","123123","aaaa"},10]),
  % [P]{"123123",
  %                     "123123",
  %                     "aaaa"}
  io:fwrite("[b]~10.16b~n", [109]),
  % [b]        6d
  io:fwrite("[B]~10.16B~n", [109]),
  % [B]        6D
  io:fwrite("[x]~10.16x~n", [109,"prefix"]),
  % [x]  prefix6d
  io:fwrite("[X]~10.16X~n", [109,"prefix"]),
  % [X]  prefix6D
  io:fwrite("[+]~10.16+~n", [109]),
  % [+]     16#6d
  io:fwrite("[#]~10.16#~n", [109]).
  % [#]     16#6D

6、Pad、Mod

Pad可以指定填充符号,默认空格:

io:fwrite("[c]~10.3.+c~n",[$a]).
% [c]+++++++aaa

Mod可以指定模式,只有t可以选择,t表示unicode:

io:format("~s",[<<"三颗豆子"/utf8>>]),
% 三颗豆子
io:format("~ts",[<<"三颗豆子"/utf8>>]).
% \x{4E09}\x{9897}\x{8C46}\x{5B50}



转载请注明出处http://www.bewindoweb.com/258.html | 三颗豆子
分享许可方式知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
重大发现:转载注明原文网址的同学刚买了彩票就中奖,刚写完代码就跑通,刚转身就遇到了真爱。
你可能还会喜欢
具体问题具体杠