-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.xml
1909 lines (1896 loc) · 232 KB
/
index.xml
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>kalifun</title>
<link>https://blog.kalifun.top/</link>
<description>Recent content on kalifun</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Fri, 19 Apr 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.kalifun.top/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>自动化状态管理:优化项目开发中的状态流转</title>
<link>https://blog.kalifun.top/post/mathmodel/fsm_demo/</link>
<pubDate>Fri, 19 Apr 2024 00:00:00 +0000</pubDate>
<author>kalifun</author>
<guid>https://blog.kalifun.top/post/mathmodel/fsm_demo/</guid>
<description>
<p><strong>有限状态机</strong>(英语:finite-state machine,缩写:FSM)又称<strong>有限状态自动机</strong>(英语:finite-state automaton,缩写:FSA),简称<strong>状态机</strong>,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型。</p>
<p>状态机是由以下几个核心组成:</p>
<ul>
<li>状态(state):表示我们常见的<code>a-&gt;b-&gt;c</code>的状态序列。</li>
<li>事件(event):触发从一个状态到另一个状态转换的条件。</li>
<li>动作(action):在从一个状态转换到另一个状态时执行的具体操作。</li>
<li>转换(transition):表示从一个状态到另一个状态的过程。</li>
</ul>
<h2 id="使用状态机的原因">
<a href="#%e4%bd%bf%e7%94%a8%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84%e5%8e%9f%e5%9b%a0" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
使用状态机的原因
</h2>
<p>随着项目的迭代,状态的数量可能会越来越多。以前可能还能通过使用<code>if</code>和<code>switch</code>语句来维护状态,但随着状态的增加,这种方法变得难以应付。状态的嵌套层级越来越深,并且许多产品还涉及到状态的回退,导致状态转换的判断变得复杂且难以维护。</p>
<p>使用状态机,我们可以根据预先定义好的状态自动进行状态流转。通过将状态和行为进行抽象和模块化,我们可以更好地管理和维护状态。</p>
<h2 id="项目实践">
<a href="#%e9%a1%b9%e7%9b%ae%e5%ae%9e%e8%b7%b5" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
项目实践
</h2>
<p>下面是一个简单的示例,展示了一个真实项目中的状态流转:</p>
<table>
<thead>
<tr>
<th>状态</th>
<th>值</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>标注待领取</td>
<td>1</td>
<td>领取: 标注中</td>
</tr>
<tr>
<td>标注中</td>
<td>2</td>
<td>提交: 内检待领取</td>
</tr>
<tr>
<td>内检待领取</td>
<td>3</td>
<td>领取: 内检中</td>
</tr>
<tr>
<td>内检中</td>
<td>4</td>
<td>提交: 验收待领取 打回: 标注待领取</td>
</tr>
<tr>
<td>验收待领取</td>
<td>5</td>
<td>领取: 验收中</td>
</tr>
<tr>
<td>验收中</td>
<td>6</td>
<td>提交: 已完成 打回: 内检待领取</td>
</tr>
<tr>
<td>已完成</td>
<td>7</td>
<td></td>
</tr>
</tbody>
</table>
<p>在这个例子中,我们先构建了一个状态和操作的映射表(Map),然后根据事件来判断要执行的操作。如果存在对应的事件和操作,就进行状态的转换。这样就完成了整个流程。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span><span class="lnt">66
</span><span class="lnt">67
</span><span class="lnt">68
</span><span class="lnt">69
</span><span class="lnt">70
</span><span class="lnt">71
</span><span class="lnt">72
</span><span class="lnt">73
</span><span class="lnt">74
</span><span class="lnt">75
</span><span class="lnt">76
</span><span class="lnt">77
</span><span class="lnt">78
</span><span class="lnt">79
</span><span class="lnt">80
</span><span class="lnt">81
</span><span class="lnt">82
</span><span class="lnt">83
</span><span class="lnt">84
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">&#34;fmt&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nf">Run</span><span class="p">(</span><span class="nx">Default</span><span class="p">,</span> <span class="nx">Submit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nf">Run</span><span class="p">(</span><span class="nx">MarkPick</span><span class="p">,</span> <span class="nx">Submit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nf">Run</span><span class="p">(</span><span class="nx">Mark</span><span class="p">,</span> <span class="nx">Submit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nf">Run</span><span class="p">(</span><span class="nx">MarkPick</span><span class="p">,</span> <span class="nx">Receive</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nf">Run</span><span class="p">(</span><span class="nx">Check</span><span class="p">,</span> <span class="nx">CallBack</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Run</span><span class="p">(</span><span class="nx">state</span> <span class="nx">State</span><span class="p">,</span> <span class="nx">event</span> <span class="nx">Event</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">v</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">transitions</span><span class="p">[</span><span class="nx">state</span><span class="p">][</span><span class="nx">event</span><span class="p">];</span> <span class="nx">ok</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">s</span> <span class="o">:=</span> <span class="s">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">v1</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">stateName</span><span class="p">[</span><span class="nx">state</span><span class="p">];</span> <span class="nx">ok</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">s</span> <span class="p">=</span> <span class="nx">v1</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">s2</span> <span class="o">:=</span> <span class="s">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">v2</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">stateName</span><span class="p">[</span><span class="nx">v</span><span class="p">];</span> <span class="nx">ok</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">s2</span> <span class="p">=</span> <span class="nx">v2</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;当前状态: %s, 事件: %s, 后来状态: %s\n&#34;</span><span class="p">,</span> <span class="nx">s</span><span class="p">,</span> <span class="nx">event</span><span class="p">,</span> <span class="nx">s2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;当前状态无法流转&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">State</span> <span class="kt">uint8</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">const</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Default</span> <span class="p">=</span> <span class="kc">iota</span>
</span></span><span class="line"><span class="cl"> <span class="nx">MarkPick</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Mark</span>
</span></span><span class="line"><span class="cl"> <span class="nx">InternalPick</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Internal</span>
</span></span><span class="line"><span class="cl"> <span class="nx">CheckPick</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Check</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Finish</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">stateName</span> <span class="p">=</span> <span class="kd">map</span><span class="p">[</span><span class="nx">State</span><span class="p">]</span><span class="kt">string</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Default</span><span class="p">:</span> <span class="s">&#34;默认&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">MarkPick</span><span class="p">:</span> <span class="s">&#34;标注待领取&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Mark</span><span class="p">:</span> <span class="s">&#34;标注中&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">InternalPick</span><span class="p">:</span> <span class="s">&#34;内检待领取&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Internal</span><span class="p">:</span> <span class="s">&#34;内检中&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">CheckPick</span><span class="p">:</span> <span class="s">&#34;验收待领取&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Check</span><span class="p">:</span> <span class="s">&#34;验收中&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Finish</span><span class="p">:</span> <span class="s">&#34;已完成&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Event</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">const</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Receive</span> <span class="p">=</span> <span class="s">&#34;Receive&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Submit</span> <span class="p">=</span> <span class="s">&#34;Submit&#34;</span>
</span></span><span class="line"><span class="cl"> <span class="nx">CallBack</span> <span class="p">=</span> <span class="s">&#34;CallBack&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">transitions</span> <span class="p">=</span> <span class="kd">map</span><span class="p">[</span><span class="nx">State</span><span class="p">]</span><span class="kd">map</span><span class="p">[</span><span class="nx">Event</span><span class="p">]</span><span class="nx">State</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">MarkPick</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Receive</span><span class="p">:</span> <span class="nx">Mark</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Mark</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Submit</span><span class="p">:</span> <span class="nx">InternalPick</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">InternalPick</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Receive</span><span class="p">:</span> <span class="nx">Internal</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Internal</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Submit</span><span class="p">:</span> <span class="nx">CheckPick</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">CallBack</span><span class="p">:</span> <span class="nx">MarkPick</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">CheckPick</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Receive</span><span class="p">:</span> <span class="nx">Check</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Check</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">CallBack</span><span class="p">:</span> <span class="nx">InternalPick</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Submit</span><span class="p">:</span> <span class="nx">Finish</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在这个示例中,我们定义了一个<code>State</code>类型和一个<code>Event</code>类型,分别表示状态和事件。然后,我们使用<code>transitions</code>来表示状态之间的转换关系,其中<code>transitions</code>是一个嵌套的映射表,它的键是起始状态,值是一个映射表,该映射表的键是事件,值是目标状态。</p>
<p>我们还定义了一个<code>Run</code>函数,它接受当前状态和触发的事件作为参数。在<code>Run</code>函数中,我们首先检查是否存在从当前状态到目标状态的转换路径,如果存在,就执行相应的操作,并输出当前状态、触发的事件和目标状态。如果不存在转换路径,就输出&quot;当前状态无法流转&quot;。</p>
<p>通过调用<code>Run</code>函数,我们可以模拟状态机的状态流转过程。在示例中的<code>main</code>函数中,我们执行了几个状态流转的例子,然后输出了相应的结果。</p>
<p>这个示例只是一个简单的演示,实际项目中的状态流转可能会更加复杂。在实际应用中,你可以根据项目的需求和业务逻辑来定义和扩展状态机的状态、事件和转换规则。</p>
<h2 id="参考资料">
<a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
参考资料
</h2>
<ul>
<li><a href="https://zh.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA">有限状态机</a>(维基百科)</li>
</ul>
</description>
</item>
<item>
<title>Workflow Wizard</title>
<link>https://blog.kalifun.top/post/workflow/workflow_wizard/</link>
<pubDate>Mon, 25 Mar 2024 00:00:00 +0000</pubDate>
<author>kalifun</author>
<guid>https://blog.kalifun.top/post/workflow/workflow_wizard/</guid>
<description>
<blockquote>
<p>工欲善其事,必先利其器</p>
</blockquote>
<p>这个是记录自己在工作流上感觉很方便,很好用的工具集。可能会随着时间的推移它会变得越来越有效率。</p>
<p>你也可以理解我正在直播带货,我会将这些好用的工具分享给各位,但不用担心他们都是免费的。</p>
<p>我会按照工具的分类来介绍,也会提供一些简单的玩法,更多可能需要你自己的探索。</p>
<h2 id="输入法">
<a href="#%e8%be%93%e5%85%a5%e6%b3%95" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
输入法
</h2>
<p>输入法是日常工作中必不可少的工具,选择一个高效的输入方案可以极大提高输入速度。本人推荐使用<strong>双拼</strong>输入方案,相比全拼,它只需通过声母+韵母的组合即可输入所需的汉字,击键次数更少,输入效率更高。</p>
<blockquote>
<p><strong>双拼</strong>是<a href="https://zh.wikipedia.org/wiki/%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E8%BE%93%E5%85%A5%E6%B3%95" title="汉语拼音输入法">汉语拼音输入法</a>的一种编码方案。相对于<a href="https://zh.wikipedia.org/wiki/%E5%85%A8%E6%8B%BC" title="全拼">全拼</a>而言,使用双拼输入<a href="https://zh.wikipedia.org/wiki/%E6%B1%89%E5%AD%97" title="汉字">汉字</a>时只需输入一个代表<a href="https://zh.wikipedia.org/wiki/%E5%A3%B0%E6%AF%8D" title="声母">声母</a>的字母,一个代表<a href="https://zh.wikipedia.org/wiki/%E9%9F%B5%E6%AF%8D" title="韵母">韵母</a>的字母,就可以打出任意一个中文字了。</p>
</blockquote>
<p>我举个简单的例子:</p>
<ul>
<li>全拼
<ul>
<li><code>双 s h u a n g</code> 我们需要输入<code>6</code>次</li>
</ul>
</li>
<li>双拼
<ul>
<li><code>双 sh uang</code>我们只需要输入<code>2</code>次</li>
</ul>
</li>
</ul>
<p>那会好奇,键盘上没有这种组合键啊?其实和五笔是一个逻辑,就是它有自己的一套标准,需要我们记忆键位,才能完美的输出自己想要的字。市面有很多双拼方案,他们的键位映射是不一样的,所以可以先去了解不同的方案的键位,我们这边推荐<code>小鹤双拼</code>。</p>
<h3 id="小鹤双拼">
<a href="#%e5%b0%8f%e9%b9%a4%e5%8f%8c%e6%8b%bc" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
小鹤双拼
</h3>
<p><img loading="lazy"
src="https://flypy.cc/assets/img/heup.png"
alt=""
/></p>
<p>当我们输入<code>双</code>的时候,我们只需要<code>u</code> + <code>l</code>,就可以了,这个需要自己形成肌肉记忆。推荐看看<a href="https://flypy.com/">官网</a>,会有一些记忆法可以帮助到你。</p>
<p>如果对输入法隐私有所顾虑,也可以考虑使用开源的<strong>Rime</strong>输入法引擎,它支持高度定制,并且无需连接在线服务器。</p>
<h2 id="启动器">
<a href="#%e5%90%af%e5%8a%a8%e5%99%a8" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
启动器
</h2>
<h3 id="raycasthttpswwwraycastcom">
<a href="#raycasthttpswwwraycastcom" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
<a href="https://www.raycast.com/">Raycast</a>
</h3>
<blockquote>
<p>Raycast is a blazingly fast, totally extendable launcher. It lets you complete tasks, calculate, share common links, and much more.</p>
</blockquote>
<p>具体使用这边就不介绍了,它是一个功能丰富的启动器,我们可以自定义启动器的快捷键,我这边的是<code>option</code> + <code>space</code>. 然后你可以同通过启动器来启动软件,不再需要翻软件列表了。当然它有很多的功能,<code>日历</code>,<code>剪切板历史</code>,<code>窗口管理</code>等&hellip;</p>
<h4 id="hotkey">
<a href="#hotkey" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
Hotkey
</h4>
<p>你可以理解它其实就是全局的快捷键,我们可以将常用的<code>application</code>设置<code>hotkey</code>。这样我们可以快速的打开它。换着快速切换到它活跃的窗口。</p>
<h4 id="window-management">
<a href="#window-management" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
Window Management
</h4>
<p>我们会不会经常需要左边打开浏览器,右边打开编辑器。你还在那不断的拖拽窗口来调整他们的大小吗?</p>
<p>很惊喜,<code>Raycast</code>自带窗口管理器,我们可以通过它的<code>command</code>或者自己设置<code>hotkey</code>来进行窗口管理。</p>
<p>它拥有丰富的插件库,如果你感兴趣可以去翻翻,还有很多好的功能。</p>
<h2 id="终端">
<a href="#%e7%bb%88%e7%ab%af" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
终端
</h2>
<h3 id="wezterm">
<a href="#wezterm" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
Wezterm
</h3>
<blockquote>
<p><em>WezTerm is a powerful cross-platform terminal emulator and multiplexer written by <a href="https://github.com/wez/"></a><a href="https://github.com/wez" title="GitHub User: wez">@wez</a> and implemented in <a href="https://www.rust-lang.org/">Rust</a></em></p>
</blockquote>
<p>如果喜欢在终端上编程的同学,也许它是一个不错的选择。它可以使用<code>lua</code>进行配置,并自定义快捷键来对<code>pane</code>进行操作。如果你是<code>win</code>+<code>wsl</code>的用户,我真心推荐。</p>
<h4 id="fzfhttpsgithubcomjunegunnfzf">
<a href="#fzfhttpsgithubcomjunegunnfzf" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
<a href="https://github.com/junegunn/fzf">fzf</a>
</h4>
<blockquote>
<p>fzf is a general-purpose command-line fuzzy finder.</p>
</blockquote>
<p>我会用于搜索目录,并通过<code>tmux</code>来创建一个<code>session</code></p>
<h4 id="zoxidehttpsgithubcomajeetdsouzazoxide">
<a href="#zoxidehttpsgithubcomajeetdsouzazoxide" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
<a href="https://github.com/ajeetdsouza/zoxide">zoxide</a>
</h4>
<blockquote>
<p>A smarter cd command. Supports all major shells.</p>
</blockquote>
<p>如果我们配置好了<code>zoxide</code>后,我们进入过一个文件夹<code>/Users/kalifun/Code/github/openCore</code>下次我们还这样输入完整路径?No!我们可以模糊匹配。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">z github open
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="浏览器">
<a href="#%e6%b5%8f%e8%a7%88%e5%99%a8" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
浏览器
</h2>
<h3 id="arc">
<a href="#arc" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
Arc
</h3>
<p>感觉是一个用了就回不去的浏览器,它虽然是<code>Chromium</code>内核,但确在改变我们使用正常浏览器的思路。
我想我们的浏览器tab页多到头皮发麻吧,但很多页面呢都是搜索引擎的列表什么的。<code>Arc</code>可以悬浮查看页面,如果满意可以全屏,如果不满意就直接关闭了这个检索结果。或者你在浏览博客,有人引入了其他的页面,你想看看写的是什么,它可以直接<code>split</code>,将会分出一半的屏幕给你预览。
还有什么Workspace,还有一些ai功能,都是非常好用的。</p>
<p>这里我也没有提到扩展,有了扩展我们可以让效率再次提升。</p>
<h2 id="开发工具">
<a href="#%e5%bc%80%e5%8f%91%e5%b7%a5%e5%85%b7" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
开发工具
</h2>
<h3 id="neovim">
<a href="#neovim" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
Neovim
</h3>
<p>我非常喜欢结合<code>tmux</code>一起来使用,这样我可以同时管理多个项目,且切换起来非常方便。
大多数人一看到这个就会觉得你在装,用VSCode不用,非要用这种毛坯?一堆的快捷键,用着好繁琐。</p>
<p>这些都是让我使用它的原因,使用它我可以让我慢慢的抛弃鼠标,能键盘做的事情绝不用鼠标。
如果你觉得配置好头痛,你可以使用<code>lazyvim</code>或者其他的配置,他们都帮我配置好了,你可以直接使用。可能一些快捷键需要熟悉一下。</p>
<h3 id="tmux">
<a href="#tmux" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
tmux
</h3>
<p><code>prefix</code> + <code>w</code> 窗口列表
<code>prefix</code> + <code>b</code> 下个窗口
&hellip;&hellip;.</p>
<h2 id="总结">
<a href="#%e6%80%bb%e7%bb%93" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
总结
</h2>
<p>我这里不想过多的去讲配置,使用方法,不然每个软件都可以输出一个文章了。后面我也会写一些我的配置,也是用来记录。我觉得在工作流程中如果能用快捷键解决的就别用鼠标去点了,真的操作起来慢,还费手腕。</p>
<p>我也简单说说我这边用的爽的点吧!</p>
<ul>
<li>我要聊微信的时候<code>option</code> + <code>c</code></li>
<li>我需要打开wezterm时<code>option</code> + <code>w</code></li>
<li>我需要使用浏览器时<code>option</code> + <code>a</code></li>
<li>我在<code>Arc</code>上需要搜索<code>lazyvim</code>代码库时,<code>⌘</code> + <code>t</code>,输入<code>gh</code> + <code>tab</code> + <code>lazyvim</code>。浏览器就帮我打开<code>GitHub</code>搜索<code>lazyvim</code>代码库。
还有很多使用场景我就不一一列举,如果感兴趣我们可以交流交流。</li>
</ul>
</description>
</item>
<item>
<title>探索golang测试的多种形式</title>
<link>https://blog.kalifun.top/post/golang/tests/</link>
<pubDate>Mon, 25 Mar 2024 00:00:00 +0000</pubDate>
<author>kalifun</author>
<guid>https://blog.kalifun.top/post/golang/tests/</guid>
<description>
<p>在软件开发中,测试是确保代码质量和功能稳定性的关键步骤之一。然而,除了其在质量保证方面的重要性之外,测试还对我们的编程思想产生了深远的影响。通过本文,我们将探讨测试如何塑造我们的编程思维,以及如何通过测试驱动开发(TDD)、重构和面向对象编程等技术来提高代码质量和开发效率。</p>
<h2 id="测试的种类">
<a href="#%e6%b5%8b%e8%af%95%e7%9a%84%e7%a7%8d%e7%b1%bb" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
测试的种类
</h2>
<h3 id="单元测试">
<a href="#%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
单元测试
</h3>
<p>单元测试<strong>是一个代码块,用于验证较小、孤立的应用程序代码块(通常是函数或方法)的准确性</strong>。</p>
<p>单元测试的要求:</p>
<ul>
<li>程序需要采用这种命名规则 <code>xxx_test.go</code></li>
<li>测试函数名必须以<code>Test</code> 开头</li>
<li>测试函数参数参数是 <code>t *testing.T</code></li>
</ul>
<h3 id="性能测试">
<a href="#%e6%80%a7%e8%83%bd%e6%b5%8b%e8%af%95" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
性能测试
</h3>
<p>性能测试<strong>是采用测试手段对软件的响应及时性进行评价的一种方式</strong>。</p>
<p>性能测试的要求:</p>
<ul>
<li>程序需要采用这种命名规则 <code>xxx_test.go</code></li>
<li>测试函数名必须以<code>Benchmark</code> 开头</li>
<li>测试函数参数参数是 <code>b *testing.B</code></li>
</ul>
<h3 id="模糊测试">
<a href="#%e6%a8%a1%e7%b3%8a%e6%b5%8b%e8%af%95" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
模糊测试
</h3>
<p>模糊测试<strong>是通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法</strong>。</p>
<p>模糊测试的要求:</p>
<ul>
<li>程序需要采用这种命名规则 <code>xxx_test.go</code></li>
<li>测试函数名必须以<code>Fuzz</code> 开头</li>
<li>测试函数参数参数是 <code>f *testing.F</code></li>
</ul>
<h2 id="测试驱动开发">
<a href="#%e6%b5%8b%e8%af%95%e9%a9%b1%e5%8a%a8%e5%bc%80%e5%8f%91" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
测试驱动开发
</h2>
<p>如果采用测试驱动开发(TDD)的流程,我们会先编写测试用例,再基于测试用例来实现最小可行的代码。这种做法可以促使我们先思考设计,再动手编码,从而产生更加优雅、简洁的代码。</p>
<p>现在我们现在有一个需求,是求解矩形的面积。按照我们常规的思路我们是先实现面积的代码,然后再编写测试用例。但是在很多情况下,实现完需求就接着写其他的了。并不会编写测试用例,这样代码并不能保证它的可靠性。</p>
<p>所以我们应该采用TDD的形式来开发,会得到不一样的效果。</p>
<p>rectangle_test.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">rectangle</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="s">&#34;testing&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">TestRectangleArea</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">got</span> <span class="o">:=</span> <span class="nf">Area</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span> <span class="o">:=</span> <span class="mf">10.0</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">got</span> <span class="o">!=</span> <span class="nx">want</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">t</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;got &#39;%f&#39; want &#39;%f&#39;&#34;</span><span class="p">,</span> <span class="nx">got</span><span class="p">,</span> <span class="nx">want</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">❯ go <span class="nb">test</span> -v
</span></span><span class="line"><span class="cl"><span class="c1"># demo/rectangle [demo/rectangle.test]</span>
</span></span><span class="line"><span class="cl">./rectangle_test.go:6:9: undefined: Area
</span></span><span class="line"><span class="cl">FAIL demo/rectangle <span class="o">[</span>build failed<span class="o">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后我们再具体实现方法。</p>
<p>rectangle.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">rectangle</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Area</span><span class="p">(</span><span class="nx">width</span><span class="p">,</span> <span class="nx">height</span> <span class="kt">float64</span><span class="p">)</span> <span class="kt">float64</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">width</span> <span class="o">*</span> <span class="nx">height</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="err">❯</span> <span class="k">go</span> <span class="nx">test</span> <span class="o">-</span><span class="nx">v</span>
</span></span><span class="line"><span class="cl"><span class="o">==</span><span class="p">=</span> <span class="nx">RUN</span> <span class="nx">TestRectangleArea</span>
</span></span><span class="line"><span class="cl"><span class="o">---</span> <span class="nx">PASS</span><span class="p">:</span> <span class="nf">TestRectangleArea</span> <span class="p">(</span><span class="mf">0.00</span><span class="nx">s</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">PASS</span>
</span></span><span class="line"><span class="cl"><span class="nx">ok</span> <span class="nx">demo</span><span class="o">/</span><span class="nx">rectangle</span> <span class="mf">0.006</span><span class="nx">s</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="重构">
<a href="#%e9%87%8d%e6%9e%84" class="anchor">
<svg class="icon" aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16">
<path fill-rule="evenodd"
d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z">
</path>
</svg>
</a>
重构
</h2>
<p>上面是一个很简单的用例,我们需要考虑更多可能,所以我们可以引入<code>表格测试的概念</code>。</p>
<p>rectangle_test.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">rectangle</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="s">&#34;testing&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">TestArea</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">type</span> <span class="nx">args</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">tests</span> <span class="o">:=</span> <span class="p">[]</span><span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span> <span class="nx">args</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"> <span class="p">}{</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;the same&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">1.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;have zero&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">0.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;set float&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mf">2.1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mf">5.3</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">11.13</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;both zero&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">0.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">tt</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tests</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">t</span><span class="p">.</span><span class="nf">Run</span><span class="p">(</span><span class="nx">tt</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">got</span> <span class="o">:=</span> <span class="nf">Area</span><span class="p">(</span><span class="nx">tt</span><span class="p">.</span><span class="nx">args</span><span class="p">.</span><span class="nx">width</span><span class="p">,</span> <span class="nx">tt</span><span class="p">.</span><span class="nx">args</span><span class="p">.</span><span class="nx">height</span><span class="p">);</span> <span class="nx">got</span> <span class="o">!=</span> <span class="nx">tt</span><span class="p">.</span><span class="nx">want</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">t</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;Area() = %v, want %v&#34;</span><span class="p">,</span> <span class="nx">got</span><span class="p">,</span> <span class="nx">tt</span><span class="p">.</span><span class="nx">want</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>我们接到一个需求是计算矩形的周长,此时我们优先将测试代码实现了。</p>
<p>rectangle_test.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">TestCircumference</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kd">type</span> <span class="nx">args</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="nx">tests</span> <span class="o">:=</span> <span class="p">[]</span><span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span> <span class="kt">string</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span> <span class="nx">args</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"> <span class="p">}{</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;the same&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">4.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;have zero&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">0.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;set float&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mf">2.1</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mf">5.3</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">14.8</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">name</span><span class="p">:</span> <span class="s">&#34;both zero&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">args</span><span class="p">:</span> <span class="nx">args</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">height</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nx">width</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="nx">want</span><span class="p">:</span> <span class="mf">0.0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">tt</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">tests</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">t</span><span class="p">.</span><span class="nf">Run</span><span class="p">(</span><span class="nx">tt</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">got</span> <span class="o">:=</span> <span class="nf">Circumference</span><span class="p">(</span><span class="nx">tt</span><span class="p">.</span><span class="nx">args</span><span class="p">.</span><span class="nx">width</span><span class="p">,</span> <span class="nx">tt</span><span class="p">.</span><span class="nx">args</span><span class="p">.</span><span class="nx">height</span><span class="p">);</span> <span class="nx">got</span> <span class="o">!=</span> <span class="nx">tt</span><span class="p">.</span><span class="nx">want</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">t</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;Area() = %v, want %v&#34;</span><span class="p">,</span> <span class="nx">got</span><span class="p">,</span> <span class="nx">tt</span><span class="p">.</span><span class="nx">want</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>然后我们要实现函数时,你有没有发现和我们求面积的时候入参和出参都一样,而且它都属于矩形的计算的一种。如果我们还是按照原来的函数来进行开发,用户就会很难受,我面积周长都要传参。那我们改造一下吧!</p>
<p>rectangle.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">rectangle</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Rectangle</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">Width</span><span class="p">,</span> <span class="nx">Height</span> <span class="kt">float64</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">r</span> <span class="nx">Rectangle</span><span class="p">)</span> <span class="nf">Area</span><span class="p">()</span> <span class="kt">float64</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Width</span> <span class="o">*</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Height</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">r</span> <span class="nx">Rectangle</span><span class="p">)</span> <span class="nf">Circumference</span><span class="p">()</span> <span class="kt">float64</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">(</span><span class="nx">r</span><span class="p">.</span><span class="nx">Width</span> <span class="o">+</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>这样对于调用方来说只需要<code>new</code>一次<code>Rectangle</code>,就可以计算<code>Area</code>和<code>Circumference</code>。</p>
<p>此时我们的测试代码又报红了,我们来修改它,让它不再报错。</p>
<p>rectangle_test.go</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27