一、lists中的个别的函数:
seq >> lists:seq(0,9). 生成0,1,2,3,~,7,8,9的数字
seq >> lists:seq(0,9,3). 生成0,3,6,9的数字 中间相隔 3
map >> lists:map(F,L). 是将列表L中的值带入到fun F中执行(注: F=fun(X) -> X end)
filter >> lists:filter(F,L) 将列表L 通过过滤方法 fun F 得到结果为true的值,再生成一个新的列表
member >> lists:member(X,L) 查找列表L中是否有包含元组X 或 元素 X 结果返回true 或 false
max: >> lists:max(L) 得到列表最大值
min: >> lists:min(L) 得到列表最小值
sum: >> lists:sum(L) 得到列表的计算总和
sort >> lists:sort(L) 对列表排序
sublist >> lists:sublist([a,b,c,d,f],3). 结果为 [a,b,c] 截取列表,注意跟lists:split的区别
lists:sublist([a,b,c,d,f],3,2). 结果为 [c,d] 截取列表,从第3个开始,截取2个
concat >> lists:concat(List). 将List中不一样的类型转成
keyfind >> lists:keyfind(A,B,C) 在列表中。找到第B位的内容是A的第一个元组
subtract>> lists:subtract(List1, List2) -> List3 根据List2出现在List1的顺序依次删除其内容,如:([123212],[212]) -> [312]
二、BIF和个别函数的使用:
tokens >> string:tokens(Str,"ab") 在字符串Str中有包含a,b,ab的都将会分割成一个列表("a122b47ab44","ab") 结果为["122","47","44"]
len >> string:len(L) 得到列表或字符串的长度
字符串替换:re:replace("123", "12", "44", [global, {return, list}]). 或 re:replace("123", "12", "44", [{return, list}]). 结果“144”
tuple_size >> tuple_size(L) 得到元组的长度 ,L={1,2,3,4,5,6} 结果:6
apply >> apply(Mod,Fun,Pram) Mod:表示功能模块:-module(Mod),Fun表示功能模块里面要运行的函数,Pram表示这个函数要的参数,例如apply(server5,start,[]).
elang >> elang:get_stacktrace(); 栈跟踪:可以查看最近的栈跟踪信息
statistics >> statistics(runtime)运行时间,statistics(wall_clock)真实时间
例子: statistics(runtime),statistics(wall_clock),
for(1,10000,fun()-> spawn(fun() -> wait() end) end), // 创建10000个进程
{_,Time1}=statistics(runtime),{_,Time2}=statistics(wall_clock), // Time1为运行总时间,Time2为消耗的真实时间
whereis >> whereis(aa) 判断aa是不是被注册进程,register(aa,spawn(fun() -> 1 end)).
is_alive >> is_alive() 查看当前node() 是否活的
rand_uniform >> crypto:rand_uniform(Min, Max) 随机取值,范围在 Min <= X < Max之间,注Min和Max为整数。
uniform >> random:uniform() (参数0或1). 随机数。0:0-1之间 ; 1: 为0 - X 之间的整数
trunc >> trunc(X) 取整数,1.01235456 结果0为(integer) 1 。
round >> round(X) 四舍五入
part >> binary:part(Bin, 0, 4) 对二进制 Bin <<1,2,3,4,5,6,7,8,9>> 结果<<1,2,3,4>> 表示Bin 从第0个位置取4个长度
bit_size >> bit_size(Bin) 获取二进制的字节大小 bit_size(<<1,2>>) = 16
>>
三、时间和时间消耗方法:
当前时间 calendar:local_time(). {{Year,Month,Day},{Hour,Min,Second}}
计算时间 timer:tc(Mod, Fun, Arg) -> {Time,Value} 微秒为单位
计时器方法 timer:send_after(Time, Dest, Msg); Dest为 is_pid(Dest)或whereis(Dest)进程名字 注:timer通gen_server的超时机制实现,如果消息多了,容易响应不过来
timer:apply_after(Time, Module, Function, Arguments), Time: 毫秒
timer:cancel(Time) (未使用过)
erlang:send_after(Time, Dest, Msg) -> TimerRef; Dest为 is_pid(Dest)或whereis(Dest)进程名字
erlang:cancel_timer(TimerRef)
四、类型: when使用
1、类型判断 》》
is_atom(X):原子; is_binary(X):二进制; is_constant(X):常量; is_function(X):函数; is_function(X,N):X函数有N个参数
is_float(X):浮点数; is_integer(X):整数; is_number(X):整数或浮点数; is_tuple(X):元组; is_list(X):列表
is_pid(X):进程标识符 is_port(X):端口; is_reference(X):引用 is_record(X,Tag):X是标记为Tag记录; is_record(X,Tag,N):X标记为Tag大小为N的记录
2、函数(BIF) 》》
abs(X): 绝对值; float(X):数字X转成浮点型; trunc(X):X数字转成整数(截取) round(X):X数字转成整数(四舍五入)
hd(X): 列表X头部 length(X):列表X的长度; tl(X):列表X的尾部 size(X):X的大小,X为元组或二进制数据
element(N,X):元组X的第N个元素 node():当前节点 node(X):创建X节点,X可以是进程标识符,引用或端口 apply(M,F,A):执行M模块里F的方法中的A参数
3、类型转换
list_to_pid pid_to_list(pid(0,31,0))-> "<0.31.0>"
list_to_atom atom_to_list('aa') -> "aa"
list_to_float float_to_list(7.0) -> "7.00000000000000000000e+000"
list_to_integer integer_to_list(1) -> "1"
list_to_tuple tuple_to_list({a,b,c}) -> [a,b,c]
list_to_binary binary_to_list(<<1>>) -> [1] 注:如能转义ascll表的内容, 如1)、<<100>> -> "b" 2)、 <<"100">> -> "100"
term_to_binary binary_to_term(<<131,104,2,100,0,1,97,100,0,1,98>>)-> {a,b}
五、个别语句用法:
1、when 例:when is_atom(X),is_integer(Y);is_float(Z) 。表示判断 X是否是原子 并且 Y是否是整数 或 Z是否是浮点数。
2、if if下使用的子句为断言判断,需能判断出true或false的。
3、case case下使用的子句为模式判断,如元组,列表等形式相符就执行对应内容(条件不支持多个元素判断,如果要多个条件,应用when方式做子句)
4、++ 在使用++时类型需要先转成相同,否则结果会是出错,列表和列表使用 ++ 结果才是列表类型
5、宏 常量宏:-define(ServerName,my_first_game_server )
带参宏: 比如: -define(Eq(X,Y),X=:=Y).
全局宏: ?MACHINE (VM 名称) ?LINE 当前代码行 ?FILE 当前代码文件
条件宏 -ifdef(product).
-define(Who,"product_db_adm").
-else.// 只有if为false才走这里
-define(Who,"test_db_adm").
-endif.// if结束
6、列表解析 在使用列表解析,想打印出内容:F=fun(Z)-> io:format("__~p~n",[Z])end. [F(X) ||X<-L] 不能写成[fun(Z)-> io:format("__~p~n",[Z])end||Z <-L],原因fun是结构体
7、短路布尔 orelse(或)、andalso(与)。和普能的and,or区别在与。普通会判断本条子句的所有条件 , 而短路的前面有满足的,就不会判断之后的条件
8、ETS 表 Tab=ets:new(tab,[set/ordered_set/bag/duplicate_bag]),为表设置模式,可设置1-4种,set:键都是唯一保存最后一个唯一的,ordered_set:与set相同为键值排序
bag:键值不相同可保存,如{a,1}{a,1}为相同,duplicate_bag:只要是数据都记录(bag键和值相同越多,效率越低,ordered_set最快》set》duplicate_bag》bag)
9、块表达式 begin Expr1..Exprn end
10、ets:fun2ms 将表达式转成sql的查询结构
六、调试debug:
1、在编辑文件的时候设置文件模式为 debug格式,》》 c(server10.erl,debug_info)/ c(server10,debug_info).
2、可以在shell 中输入im(). 或 debugger:start(). 来调出debug页面 也可以用别一个:toolbar:start().
3、在页面中找到 选择Module--> Interpret --> 选择你要调试的.erl文件。
六(一) 应用程序监视器:
使用appmon:start(),可以启动它,可视化
六(二) 进程管理器:
使用pman:start(),可以启动它,可视化,和使用i()命令看到所有的进程,双击它可以追踪一个输出窗口,每个进程都 有一个自己的输出窗口
六(三) 进程管理器:(R17以上)
使用observer:start(),可以启动它,可视化,可以在processes中查看进程的使用情况
六(四) 打印栈信息
erlang:get_stacktrace()
七、节点创建方式:
八、一些小方法:(实用,内置方法)
重启进程 > supervisor:restart_child(game, socket_server_sup).
删除子进程规范:> supervisor:delete_child(game, socket_server_sup).
启动子进程 > supervisor:start_child(test_sup,Spec). Spec = {find_single_dog_sup,{find_single_dog_sup, start_link, []},permanent,16#FFFFFFFF,supervisor,[find_single_dog_sup]},
计算进程运行数 > supervisor:count_children(socket_server_sup)
13、查看系统允许进程数上限 > erlang:system_info(process_limit),使用erl +p 500000 提高进程数上限,用processes:max(5000)改变进程大小
14、注销注册名字 > erlang:unregister(RegName) -> true
15、查看当前系统使用原子数等个数> c:memory()
16、查看已注册的进程信息 > c:regs()
九、ETS的使用:
1、all() -> [Tab] :Tab >> tid() | atom() 。返回一个列表的所有表节点。命名表是由他们的名字,不知名的表给出的表标识符。
2、(1)delete(Tab) -> true 删除Table对象
(2)delete(Tab, Key) -> true 删除这个Tab的Key字段 Tab = tid() | atom() ,Key = term()
(3)delete_all_objects(Tab) -> true 删除这个Tab的全部数据。保留对象Table
(4)delete_object(Tab,Object) -> true 删除 Object为元组{Key,Value}
(5) insert(Tab,Object) ->
(6) lookup(Tab,Key) -> Object|{error,Reason}
(7) update_element(Tab,Key,[{Pos,Value}]) -> true/false pos为当前元组的位置从1开始,第一位为Key,一般不可改为Value中的值
(8) match(Tab,Pattern) -> [Match] Pattern为模式,如存的都是{aa,10}的开式,'$1'取全部内容 ,{'$1','_'}取 [[aa]] , {'_','$1'}取 [[10]],
(9) match(Tab, Pattern, Limit) -> {[Match],Continuation} | '$end_of_table' Limit为要几条记录
(10) info(TabName) 获得当前表的所有信息
(11)select(TabName, MS) MS= [#player{player_id = PlayerId, _ = '_'},[],['$_']], 查出当前表为PlayerId的数据
修改ETS表
update_counter(Tab, Key, UpdateOp) -> Result pdateOp = {Pos,Incr} | {Pos,Incr,Threshold,SetValue}
update_counter(Tab, Key, [UpdateOp]) -> [Result] Pos = Incr = Threshold = SetValue = Result = integer()
update_counter(Tab, Key, Incr) -> Result Incr表示 : 在元素Key的值加上Incr 这个方法没有Pos默认为第二个位置修改
update_element(Tab, Key, {Pos,Value}) -> true | false 为修改Tab中,Key元组的第一个元素,元组中的第Pos个位置等于Value 注:Pos(为元组的位置,从1开始,Key不可修改)
update_element(Tab, Key, [{Pos,Value}]) -> true | false
十、个别实用方法
1、 %% Number:需要处理的小数, X 要保留几位小数, float(8.22986, 3), output: 8.230
float(Number, X) -> N = math:pow(10,X), round(Number*N)/N.
2、erase : erase(Key) 擦除字典Key的内容,
3、div 为 整除 5 div 3 = 2 ; rem为取余 7 rem 3 = 1 ; / 除 5 / 2 = 2.5
十一、 标准错误日志
1、erl -boot start_clean: 创建一个适合程序开发的环境,只会提供错误日志的简单形式
2、erl -boot start_sasl -config log4: 在log4.config文件中打印,创建一个适合产品系统的环境,SASL:System Architecture Support Libraries的缩写,它负责错误日志,过载保护等
十二、 分布式方法:
1、互相连接: spawn_link(Node,Fun) -> Pid , spawn_link(Node,M,F,A) -> Pid
2、打开监视: monitor_node(Node,Flag) -> true Flag为true为开启,Flag为flas为关闭
3、解除对进程的监视最好调用erlang:demonitor(Reference, [flush]),因为demonitor调用之前监视的进程可能就DOWN掉了。
4、强制断开一个节点连接 disconnect_node(Node) -> bool()|ignored
5、本地状态正常而且还是分布式, erlang:is_alive()
6、net_adm:ping(node@Hostname) pang为失败,,,pong为成功; 查看连接了哪些 nodes()
7、手动连接 net_kernel:connect('aa@aa')
8、隐藏节点 erl -name aa@bb -hidden 查看当前隐藏节点node(hidden)
9、epmd(操作系统进程), 设置互联端口范围
1) (运行中)application:set_env(kernel,inet_dist_listen_min,9100)/(kernel,inet_dist_listen_max,9105),强制erlang分布式使用从9100到9105端口之间
2) (启动参数)-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9105
10、查看主机上的节点 net_adm:names(Host) -> {ok, [{name,Port}]} | {error, Reason}
十三、 md5加密:
md5(S) ->
Md5_bin = erlang:md5(S),
Md5_list = binary_to_list(Md5_bin),
lists:flatten(list_to_hex(Md5_list)).
%% @fun 转成16进制
%%lists:flatten(io_lib:format("~40.16.0b", [Bin])).
list_to_hex(L) ->
lists:map(fun(X) -> int_to_hex(X) end, L).
int_to_hex(N) when N < 256 ->
[hex(N div 16), hex(N rem 16)].
hex(N) when N < 10 ->
$0 + N;
hex(N) when N >= 10, N < 16 ->
$a + (N - 10).
十四、数据压缩和解压缩
zlib:compress(Bin);
zlib:uncompress(Data) => 结果:binary
十五、查看谁连接
inet:peername(Socket) -> {ok,{Ip_Address, Prot}} |{error, Why} Ip_Address:{N1,N2,N3,N4} 表示ipV4 {N1,N2,N3,N4,N5,N6} 表示ipV6
inet_parse:ntoa(Ip_Address) -> "192.168.1.100" 获得完整的Ip (注: Ip_Address格式为{192.168.22.81})
inet_parse:address("192.168.1.100"). ->{ok, {192,168,22,81}}
inet:i() 获得运行erlang运行时系统使用以及已创建的所有tcp和udp套接字(端口,sockect等信息)
十六、进程内置方法解读
1、静态子进程(监控和工作进程):
工作进程是OTP行为包,包括gen_server,gen_fsm(支持有限状态机行为包)和gen_event(提供事件处理功能), 工作进程必须把自身链接到监控进程行为包中,并处理不透露给程序员
supervisor:start_link(ServerName, CallBackModule, Arguments)
supervisor:start_link(CallBackModule, Arguments)
ServerName: 监控进程中注册的名字,格式:{local, Name} 或{global, Name}的元组,如果不注册可能第二个方法
CallBackModule: 是放置init/1回调函数的模块名字
Argument: 是init/1回调函数时传递的值
2、动态子进程
如果你需要监控进程能够动态生成子进程。用于处理特定的事件,管理任务并在完成后终止
supervisor:start_child(SupervisorName, ChildSpec) 启动进程树下的子
supervisor:terminate_child(SupervisorName, Id) 停止进程下的子进程
supervisor:restart_child(SupervisorName, Id) 重启进程树下的子进程
supervisor:delete_child(SupervisorName, Id)
SupervisorName: 可以是监控进程标识符或它的注册名
ChildSpec: 是一个单一的子进程规范元组
Id: 是在ChildSpec中定义的唯一的子进程标识符
注:在ChildSpec元组中特别重要的是子进程Id,即使在终止后,ChildSpec仍然由监控进程存储,并且通过它的Id引用,这样就允许进程可以停止和重新开始子进程,只有在删除时才能将子进程永久移除
http://www.douban.com/note/58679131/
十七、gen_tcp
1、在客户端使用gen_tcp:connet时的进程应与{tcp, Socket, Request}接收同一个进程,否则无法接收(注:如果创建新进程给gen_tcp:send(Socket, OutBin),返回接收时也是在gen_tcp:connect的进程上)
2、
十八、编译方法解读
1、编译
c:c(File) 编译然后清除一个文件代码
c:nc(File) 编译并加载一个文件在所有节点的代码
compile:file(File) 编辑一个文件
2、无法热更
code:soft_purge(Module), 如果没有process运行旧的Module,则返回true(表明此Module可以被温和的purge);否则返回false。
clde:load_file(Module), 加载模块