学习Erlang的时候在书的留白处随手记录了一些东西,还有一些记录在了demo的注释里面,今天抽时间整理出来了一部分,分享一下.

  1. Erlang的设计哲学是为每一个独立的事件创建一个新进程.
  2. Erlang的容错处理:如果不能完成一个任务就死掉 让其它正常的进程来善后。link函数就是用来建立这种进程间的双向连接来监测非正常退出,并做出处理。
  3. BIFs是built-in functions的缩写代表这些方法是Erlang运行时系统的一部分
  4. side-effect-free无副作用,其中一种定义是说:一个程序执行前后保持程序的状态不变,不改变非局部变量的值,不改变传入参数值,也无I/O
  5. 写测试模块的时候不必频繁导出函数  –compile(export_all) 就可以导出所有函数
  6. Erlang中整数值没有上限值,最大值只是受限于硬件(内存有多大)
  7. 在Erlang Shell中可以方便的做进制转换:Base#Value Base的范围2~16 2#101011
  8. Erlang Shell中查询ASCII码 $1 $a $A $\n $\}
  9. Erlang Shell中释放变量使用f() 定义record使用rd(),读取shell输入使用io:read/1可以接受输入Erlang term.
  10. Erlang Shell中接受消息使用flush() 自己的Pid是self() 查看进程信息使用processes() i() 但是不要在进程非常多的场景使用,会消耗大量内存
  11. atom是否已经注册的:registered() unregister(Pid) whereis(Atom) regs().
  12. atom能够进行的唯一运算就是比较
  13. atom是可以使用.和@的,但是别给自己添乱
  14. atom会被记录在ERT系统表中,只需要几个字节,atom之间比较起来也很快
  15. atom不参与Erlang GC,所以atom不能无节制的创建,list_to_existing_atom可以一定程度上缓解创建重复atom的内存消耗
  16. Tuple是Erlang表达复杂数据结构的手段,第一个元素经常被称作Tag,Tag Massage是Erlang编程的最佳实践
  17. Tuple索引是从1开始的,执行一下 element(1,{a,b,c}).看看 再试一下element(0,{a,b,c})看看报什么错
  18. Tuple大小使用tuple_size({1,2,3,4,5}).
  19. M++N会遍历列表M所以如果必须要使用++也要让数据量小的List在前面
  20. proplist对于处理key_value的list真的是非常方面
  21. List=[Element|List]所以你可以在shell中可以输入[1,2|3],尝试匹配一下它 [A,B,C]=[1,2|3]再试一下[P,Q]=[1,2,3]
  22. List最后一个元素是空列表[],被称作well-formed list正则列表,[1,2|3]这种结构要避免
  23. --操作符是针对元素进行的 [1,2]--[3]结果是[1,2] [2,2]--[2]结果是[2],运算顺序是从右到左, [1,2,3]--[1,2]--[1].结果是[1,3]
  24. number<atom<reference<fun<port<pid<tuple<list<binary 之所以有这样一个比较关系,就是为了支持泛型比较
  25. =:= =/=精确比较运算不仅比较值,还比较类型,效率更高
  26. Erlang GC的特点是:每个进程独立进行GC ,分代(generational garbage) ,复制回收
  27. Erlang的模式匹配作用:1.变量赋值 2.提取变量值 3.控制流
  28. 从Pid反查node信息 node(Pid)即可
  29. 写function的时候在最后添加一个catch_all的方法也被认为是最佳实践
  30. 如果可预见结果集的所有可能性,那么case语句不建议使用catch_all
  31. if语句会对Guard子句做catch,所以 if 1/0 ->a; true ->b end.的返回值是b而不是抛出异常
  32. if的Guard子句放在变量里就可以让异常抛出来:G=1/0 , if G->a; true ->b end.
  33. Guard subexpressions resulting in a runtime error are treated as returning false.
  34. Guard可以使用, ; 表达多个条件if  X=:=1,Y<2;X+Y<4 ->ok; true ->error end.
  35. process dictionary几乎被描述成洪水猛兽了,对于一次写入然后就只读的配置性数据放在进程字典应该没有问题
  36. Erlang出错法则:让错误报告在它发生的地方
  37. 查看module的元数据信息  比如a.erl a:module_info().   m(a).
  38. Erlang的元编程Meta Programming确实直接,apply/3 甚至在参数确定情况下的直接调用M:F(A)
  39. Concurrency is the ability for different functions to execute in parallel without affecting each other unless explicitly programmed to do so.
  40. 我们要遍历ETS可以使用first/next 也可以使用foldr foldl,但是后者会把ETS数据复制到进程,数据量大时有效率问题
  41. 负责进程创建职责的是Erlang VM中的Scheduler
  42. spawn第三个参数是List,这个调用的时候注意!!
  43. Spawning a process will never fail!!!
  44. Sending a message will never fail!!!
  45. receive子句的处理逻辑抽取为一个独立的方法是推荐的做法
  46. receive如果接受到没有匹配任何子句的消息,那么这条消息就会保存在mailbox,长此以往就会耗尽内存系统崩溃之险;
  47. 消息发送的速度快于进程处理的速度就会增加CPU上的消耗,因为会反复扫描mailbox
  48. Not handling unknown messages should therefore be treated as a bug. 匹配未知消息会导致难以发现错误,所以这些位置要记录日志
  49. 选择性接受和mailbox这两个东西就解决了消息接受缓冲区的问题
  50. A race condition occurs when the behavior of a system depends on the order in which certain events occur: these events “race” to influence the behavior.
  51. 上面两个不失败的设计原则是为了解除进程依赖:另外一个进程的创建和接受消息是否成功不影响当前进程的正常执行
  52. timer:tc/3计算方法的执行时间 这个构建简单的性能测试很方便
  53. {'EXIT', Pid, Reason}退出消息的格式包含的信息:谁因为什么退出了
  54. exit(Pid,normal) 这个消息会被进程忽略掉.
  55. process_flag(trap_exit, true).退出截获的决策当然是在生命周期的早期进行配置。所以一般出现在init阶段。
  56. 截获到底做了一件什么事情呢?把退出消息放在进程收件箱中当成一个普通的消息来处理。这就相当于我们把异常信息放在返回结果中的情况
  57. receive接收并处理退出信号,退出消息被截获就不再传播
  58. link是双向的,monitor是单向的,被监控的进程死掉后,监控进程会收到  {'DOWN',Reference,process,Pid,Reason} 消息
  59. 如果接收到{'EXIT', Pid, Reason}的进程没有trap_exit,而且Reason不是normal,这个进程就会终止掉并继续传播这个退出消息
  60. 所有的BIFs的执行都是原子性的,所以spawn_link不等同于spawn 和 link的组合调用;之所以有spawn_link是因为有些时候创建进程的时候还没有来得及做link,进程就死掉了;所以这个方法把这两个行为做成了原子性的操作
  61. {'EXIT', Pid, Reason}Reason如果是kill,关联进程无论是否trap_exit都会死掉
  62. {'EXIT', Pid, Reason}Reason如果是normal,关联进程trap_exit会收到一条{'EXIT', Pid, normal}消息,如果没有trap_exit什么都不会发生
  63. 在崩溃的进程调用 erlang:get_stacktrace/0 可以得到调用的堆栈信息
  64. 可以使用record_info()来查看record定义
  65. erlang读取命令行参数使用: init:get_argument(Key), or init:get_arguments()
  66. BIF不自动导入 -compile({no_auto_import,[F/A]}).
  67. include_lib和include类似,但是不是指向绝对路径的文件,路径中的第一部分是application的名称 比如:
    -include_lib("kernel/include/file.hrl").

    12> code:lib_dir(kernel).
    "/usr/local/lib/erlang/lib/kernel-3.0"

  68. ETS也是不参与GC的
  69. erlang:error(Reason) 会结束当前进程的执行,如果捕获异常会得到方法调用的堆栈信息,当方法不知道该如何执行的时候选择这样做.要分清正常的逻辑分支与错误.
     
    exit和error的区别在于使用意图:是仅仅遇到一个错误还是遇到极端情况需要干掉当前进程.细节上的区别是erlang:error/1返回stack trace,exit/1不包含此信息.如果堆栈信息量非常大,或者调用参数数据量非常大,exit信息会拷贝数据到所有相关的进程.
     
     
    throw出来的信息实际上是想开发者来处理的,与上面两种表现错误的形式不同,throw并不包含让进程崩溃的意图,更多的是实现控制流转.所以很多人把throw当做return来用.
  70. Erlang是动态强类型的语言 dynamic-strong Typing
  71. windows环境Erlang GUI工具:toolbar:start(). tv:start() pman:start(). appmon:start() debugger:start()
  72. 还有一个WebUI的工具 webtool:start().
  73. Note: Using the form [1 | 2] gives what we call an 'improper list'. Improper lists will work when you pattern match in the [Head|Tail] manner, but will fail to be used with standard functions of Erlang (even length()). This is because Erlang expects proper lists. Proper lists end with an empty list as their last cell. When declaring an item like[2], the list is automatically formed in a proper manner. As such, [1|[2]] would work! Improper lists, although syntactically valid, are of very limited use outside of user-defined data structures.
  74. 在EShell中执行Erlang方法
    $> erl -boot start_clean -noshell -eval 'io:format("hi\n")' -eval 'halt(0)'
    % or
    $> erl -boot start_clean -noshell -eval 'io:format("hi\n"), halt(0)'

    % example:
    erl -sname ad_service -eval 'ok=mnesia:create_schema([node()]).' -s init stop

  75. 打印浮点型
    lists:flatten(io_lib:format("~.*..f", [2, S]));

    3> lists:flatten(io_lib:format("~.*..f", [2, 192.2225])).
    "192.22"
    4> lists:flatten(io_lib:format("~.*..f", [3, 192.2225])).
    "192.223"

    5> lists:flatten([io_lib:format("~8.2.0B,", [L]) || L <- [1,2,3]]).
    "00000001,00000010,00000011,"
    6> lists:flatten([io_lib:format("~2.16.0B ", [L]) || L <- [1,2,3]]).
    "01 02 03 ".

  76. 找出消耗内存最多的进程
    lists:reverse(lists:keysort(2,[{P, erlang:process_info(P, heap_size)} || P <- erlang:processes()])).

  77. flush进程接收到的消息,不断的从消息队列里面取消息,当消息队列为空的时候马上退出;receive after 0 如果mail box里面没有匹配的消息马上超时
    1
    2
    3
    4
    5
    6
    flush() ->
        receive
            _ -> flush()
        after 0 ->
            ok
        end.

      

  78. 找到最消耗内存的ETS表
    lists:reverse(lists:keysort(2,[{T, ets:info(T, memory)} || T <- ets:all()])).

  79. record类型作为参数的小技巧
    -record(x,{name,zz}).
    -record(y,{yy,name}).
    -export([test1/0,test2/0]).
    -define(create(Type,Name),#Type{name = Name}).

    test1() -> ?create(x,"Noel"). % -> {x,"Noel",undefined}
    test2() -> ?create(y,"Noel"). % -> {y,undefined,"Noel"}

  80. binary_to_list VS bitstring_to_list

    1> A = <<1:2, 23:6>>.
    <<"W">>
    2> B = <<1:2, 23:5>>.
    <<55:7>>
    3> binary_to_list(A).
    "W"
    4> binary_to_list(B).
    ** exception error: bad argument
    in function binary_to_list/1
    called as binary_to_list(<<55:7>>)
    5> bitstring_to_list(A).
    "W"
    6> bitstring_to_list(B).
    [<<55:7>>]

  81. Erlang执行操作系统命令 os:cmd("uptime").

  82. [3] or "3"
    17> [51] =:= "3".
    true
    18> [3] =:= "3".
    false
    19>

  83. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    26>  MyTerm = {atom, <<"binary">>, 1}.
    {atom,<<"binary">>,1}
    27> MyList = [ MyTerm || _ <- lists:seq(1, 100) ].
    [{atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"binary">>,1},
     {atom,<<"bina"...>>,1},
     {atom,<<...>>,...},
     {atom,...},
     {...}|...]
    28>  erts_debug:size(MyList).
    210
    29> erts_debug:flat_size(MyList).
    1200
    30>

      

  84. 如果仅仅是将一系列的模块打包在一起,并不需要启动application,那么只需要在app文件中移除掉{mod,{Module,Args}}配置节即可.这种Libiary Application典型范例就是stdlib.
    看配置文件:

  85. erlang:now常用作随机数的种子,这个并不是太好,建议使用:

    4> <<A:32,B:32,C:32>> = crypto:strong_rand_bytes(12) .
    <<42,136,117,238,28,89,154,241,88,189,70,139>>
    5> b().
    A = 713586158
    B = 475634417
    C = 1488799371
    ok
  86. 启动脚本可以使用escript来写

    1
    2
    3
    4
    5
    #!/usr/bin/env escript
    %% -*- erlang -*-
    %%! -pa 'ebin/' [Other erl Arguments]
    main([StringArguments]) ->
                           ....
  87. erlang启动过程可以通过-init_debug参数查看,erl启动不成功的时候就方便了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [root@nimbus ~]# erl  -init_debug
    {progress,preloaded}
    {progress,kernel_load_completed}
    {progress,modules_loaded}
    {start,heart}
    {start,error_logger}
    {start,application_controller}
    {progress,init_kernel_started}
    {apply,{application,load,[{application,stdlib,[{description,"ERTS  CXC 138 10"},{vsn,"2.0"},{id,[]},{modules,[array,base64,beam_lib,binary,c,calendar,dets,dets_server,dets_sup,dets_utils,dets_v8,dets_v9,dict,digraph,digraph_utils,edlin,edlin_expand,epp,eval_bits,erl_bits,erl_compile,erl_eval,erl_expand_records,erl_internal,erl_lint,erl_parse,erl_posix_msg,erl_pp,erl_scan,erl_tar,error_logger_file_h,error_logger_tty_h,escript,ets,file_sorter,filelib,filename,gb_trees,gb_sets,gen,gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,io_lib_fread,io_lib_pretty,lib,lists,log_mf_h,maps,math,ms_transform,orddict,ordsets,otp_internal,pg,pool,proc_lib,proplists,qlc,qlc_pt,queue,random,re,sets,shell,shell_default,slave,sofs,string,supervisor,supervisor_bridge,sys,timer,unicode,win32reg,zip]},{registered,[timer_server,rsh_starter,take_over_monitor,pool_master,dets]},{applications,[kernel]},{included_applications,[]},{env,[]},{maxT,infinity},{maxP,infinity}]}]}}
    {progress,applications_loaded}
    {apply,{application,start_boot,[kernel,permanent]}}
    Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]
     
    {apply,{application,start_boot,[stdlib,permanent]}}
    {apply,{c,erlangrc,[]}}
    {progress,started}
    Eshell V6.0  (abort with ^G)
    1>

      

  88. Erlang Beam Format
     
    Python module to parse Erlang BEAM files.

     

  89. erlydtl真的让Erlang Web开发有了幸福感

    Eshell V5.6.5  (abort with ^G)
    1> erlydtl_dateformat:format(erlang:localtime(),  "Y-m-d H:i:s").
    "2009-10-03 16:55:40"

    It implements most of the tags of the original django date formatting,
    (which itself is based on http://php.net/date) which is documented
    here :
    http://docs.djangoproject.co

     
     

并发&并行  concurrency and parallelism.

In many places both words refer to the same concept. They are often used as two different ideas in the context of Erlang. For many Erlangers, concurrency refers to the idea of having many actors running independently, but not necessarily all at the same time. Parallelism is having actors running exactly at the same time. I will say that there doesn't seem to be any consensus on such definitions around various areas of computer science, but I will use them in this manner in this text. Don't be surprised if other sources or people use the same terms to mean different things.

This is to say Erlang had concurrency from the beginning, even when everything was done on a single core processor in the '80s. Each Erlang process would have its own slice of time to run, much like desktop applications did before multi-core systems.

Parallelism was still possible back then; all you needed to do was to have a second computer running the code and communicating with the first one. Even then, only two actors could be run in parallel in this setup. Nowadays, multi-core systems allows for parallelism on a single computer (with some industrial chips having many dozens of cores) and Erlang takes full advantage of this possibility.

The distinction between concurrency and parallelism is important to make, because many programmers hold the belief that Erlang was ready for multi-core computers years before it actually was. Erlang was only adapted to true symmetric multiprocessing in the mid 2000s and only got most of the implementation right with the R13B release of the language in 2009. Before that, SMP often had to be disabled to avoid performance losses. To get parallelism on a multicore computer without SMP, you'd start many instances of the VM instead.

An interesting fact is that because Erlang concurrency is all about isolated processes, it took no conceptual change at the language level to bring true parallelism to the language. All the changes were transparently done in the VM, away from the eyes of the programmers.

Erlang Type

Through the years, there were some attempts to build type systems on top of Erlang. One such attempt happened back in 1997, conducted by Simon Marlow, one of the lead developers of the Glasgow Haskell Compiler, and Philip Wadler, who worked on Haskell's design and has contributed to the theory behind monads (Read the paper on said type system). Joe Armstrong latercommented on the paper:

One day Phil phoned me up and announced that a) Erlang needed a type system, b) he had written a small prototype of a type system and c) he had a one year’s sabbatical and was going to write a type system for Erlang and “were we interested?” Answer —“Yes.”

Phil Wadler and Simon Marlow worked on a type system for over a year and the results were published in [20]. The results of the project were somewhat disappointing. To start with, only a subset of the language was type-checkable, the major omission being the lack of process types and of type checking inter-process messages.

 

二进制列表解析

%%The only change in syntax from regular list comprehensions is the <- which became <= and using binaries (<<>>) instead of lists ([]). 

1> Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
2> RGB = [ {R,G,B} || <<R:8,G:8,B:8>> <= Pixels ].
[{213,45,132},{64,76,32},{76,0,0},{234,32,15}]
3> << <<R:8, G:8, B:8>> || {R,G,B} <- RGB >>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
4> << <<R:8, G:8, B:8>> || {R,G,B} <- RGB >>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
5> << <<Bin>> || Bin <- [<<3,7,5,4,7>>] >>.
** exception error: bad argument
6> << <<Bin/binary>> || Bin <- [<<3,7,5,4,7>>] >>.
<<3,7,5,4,7>>
7> << <<(X+1)/integer>> || <<X>> <= <<3,7,5,4,7>> >>.
<<4,8,6,5,8>>

Note: At the time of this writing, binary comprehensions were seldom used and not documented very well. As such, it was decided not to dig more than what is necessary to identify them and understand their basic working. To understand more bit syntax as a whole, read the white paper defining their specification.

  To be continued...

Erlang 杂记的更多相关文章

  1. [Erlang 0118] Erlang 杂记 V

       我在知乎回答问题不多,这个问题: "对你职业生涯帮助最大的习惯是什么?它是如何帮助你的?",我还是主动回答了一下.    做笔记 一开始笔记软件做的不好的时候就发邮件给自己, ...

  2. [Erlang 0129] Erlang 杂记 VI

    把之前阅读资料的时候记下的东西,整理了一下. Adding special-purpose processor support to the Erlang VM   P23 简单介绍了Erlang C ...

  3. Erlang标准数据结构的选择

    Erlang标准数据结构的选择(金庆的专栏)gen_server with a dict vs mnesia table vs etshttp://stackoverflow.com/question ...

  4. [Erlang 0128] Term sharing in Erlang/OTP 下篇

    继续昨天的话题,昨天提到io:format对数据共享的间接影响,如果是下面两种情况恐怕更容易成为"坑", 呃,恰好我都遇到过; 如果是测试代码是下面这样,得到的结果会是怎样?猜! ...

  5. [Erlang 0127] Term sharing in Erlang/OTP 上篇

    之前,在 [Erlang 0126] 我们读过的Erlang论文 提到过下面这篇论文: On Preserving Term Sharing in the Erlang Virtual Machine ...

  6. [Erlang 0126] 我们读过的Erlang论文

    我在Erlang Resources 豆瓣小站上发起了一个征集活动 [链接] ,"[征集] 我们读过的Erlang论文",希望大家来参加.发起这样一个活动的目的是因为Erlang相 ...

  7. [Erlang 0125] Know a little Erlang opcode

    Erlang源代码编译为beam文件,代码要经过一系列的过程(见下面的简图),Core Erlang之前已经简单介绍过了Core Erlang,代码转换为Core Erlang,就容易拨开一些语法糖的 ...

  8. [Erlang 0124] Erlang Unicode 两三事 - 补遗

    最近看了Erlang User Conference 2013上patrik分享的BRING UNICODE TO ERLANG!视频,这个分享很好的梳理了Erlang Unicode相关的问题,基本 ...

  9. [Erlang 0123] Erlang EPMD

     epmd进程和Erlang节点进程如影随形,在Rabbitmq集群,Ejabberd集群,Couchbase集群产品文档中都会有相当多的内容讲epmd,epmd是什么呢?   epmd 是Erlan ...

随机推荐

  1. 【习题 6-1 UVA-673】Parentheses Balance

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 括号匹配. 栈模拟就好. 多种括号也是一样可以做的. [代码] #include <bits/stdc++.h> usi ...

  2. 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输

    https://www.luogu.org/problem/show?pid=1967#sub  ||  http://www.cogs.pro/cogs/problem/problem.php?pi ...

  3. LuceneIndexFileDeleter会保留初始的commit

    给实时索引加入了merge策略,持续更新时发现有做merge,但索引文件夹中的段数远远大于RealTimeIndexWriter中的段数,就是有些merge的段应该删除,文件夹中没有删除.而关闭sea ...

  4. 让自己的软件实现拖拽打开文件(覆盖WM_DROPFILES,使用DragQueryFile,DragFinish API函数)

    作者: 帅宏军 //声明 protected    procedure WMDROPFILES(var Msg : TMessage); message WM_DROPFILES; --------- ...

  5. Searching with regular sentences will only get you so far – if you need to find something a bit tricky turn to these advanced yet simple methods--转

    原文地址:http://www.theguardian.com/technology/2016/jan/15/how-to-use-search-like-a-pro-10-tips-and-tric ...

  6. 账号被盗!请勿在CSDN,回复不论什么消息。

    账号被盗!请勿在CSDN,回复不论什么消息.

  7. HDU 3974 Assign the task 并查集

    http://acm.hdu.edu.cn/showproblem.php?pid=3974 题目大意: 一个公司有N个员工,对于每个员工,如果他们有下属,那么他们下属的下属也是他的下属. 公司会给员 ...

  8. 数据结构与算法实验题 4.2 Who is the strongest

    数据结构与算法实验题 4.2 Who is the strongest ★实验任务 在神奇的魔法世界,召唤师召唤了一群的魁偶.这些魁偶排成一排,每个魁偶都有一个 战斗值.现在该召唤师有一个技能,该技能 ...

  9. 【81.82%】【codeforces 740B】Alyona and flowers

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  10. 简要分析unity3d中剪不断理还乱的yield

    在学习unity3d的时候非常easy看到以下这个样例: void Start () { StartCoroutine(Destroy()); } IEnumerator Destroy(){ yie ...