-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathgo_language.language.txt
995 lines (835 loc) · 56.5 KB
/
go_language.language.txt
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
┏━━━━━━━━━━━━━━━━━┓
┃ GO LANGUAGE ┃
┗━━━━━━━━━━━━━━━━━┛
TODO:
- https://golang.org/pkg/
- after io package:
- https://golang.org/doc/effective_go.html#printing
- https://golang.org/pkg/testing/iotest
- after time package
- https://github.com/golang/go/wiki/Timeouts
- https://github.com/golang/go/wiki/RateLimiting
- https://blog.golang.org
- https://github.com/golang?type=source
- https://pkg.go.dev/golang.org/x/tools
- add VSCode shortcuts
- specific tools:
- lists:
- go through to_learn.txt
- https://github.com/golang/go/wiki/CodeTools
- https://github.com/golang/go/wiki/Projects
- https://github.com/golang/go/wiki/LearnServerProgramming#toolkits-and-frameworks
- https://github.com/avelino/awesome-go
- debuggers:
- delve
- https://rakyll.org/coredumps/
- runtime version management:
- https://bitbucket.org/ymotongpoo/goenv/src/develop/
- https://github.com/syndbg/goenv
- https://github.com/moovweb/gvm
- dependencies updates:
- https://github.com/psampaz/go-mod-outdated
- https://github.com/oligot/go-mod-upgrade
- linting:
- https://github.com/golangci/golangci-lint
- https://github.com/golang/lint
VERSION ==> #1.16.7
#Semver is respected for both language and standard library
# - not the "sub-repositories" libraries
# - not the go CLI
CORE DOCUMENTATION ==> #Core:
# - go_language
# - go_standard_library
#Tools:
# - go_cli
# - go_modules
# - go_build
#Linting|beautifying:
# - go_fmt
# - go_vet
# - go_msan
#Documentation:
# - go_doc
# - godoc
#Testing:
# - go_test
# - go_examples
# - testing_quick
# - go_test_cover
# - go_test_bench
#Debugging:
# - go_profiling
# - go_tracing
# - go_concurrency_debugging
#Code generation:
# - go_fix
# - go_generate
#Publishing:
# - pkg_go_dev
┌─────────────┐
│ GENERIC │
└─────────────┘
SOURCE CODE ENCODING ==> #UTF-8, non-canonicalized
TOKEN TYPES ==> # - identifier: VAR|TYPE, FUNC (including pre-defined), true|false|iota|nil
# - keyword: return|if|package|const|...
# - operator|punctuation: + & ; . <<= () [] {} ...
# - literals: [U]INT|FLOAT|COMPLEX '...' "..."
WHITESPACES ==> #\t \r \n space. Separate tokens. Ignored otherwise
EXPR[;] #; can be a newline instead (recommended) when line ends with:
# - VAR
# - NUM|STR|RUNE
# - ) ] } ++ --
# - return|break|continue|fallthrough
#I.e. most of the time.
; #Empty statement
(VAL) #Parenthesis can be used to override operator precedence
// COMMENT
/* COMMENT */ #
VARIABLE NAME ==> #VAR|FUNC|TYPE|LABEL|PACKAGE name must not be a language keyword or a "universe block" identifier
#Must contain only letters, _ or (except first char) digit
# - can use non-ASCII letter|digit
#Recommended camelCase over snake_case
┌───────────┐
│ LOOPS │
└───────────┘
if [EXPR;] BOOL_EXPR { ... }
[else if [EXPR;] BOOL_EXPR {...}]
...
[else { ... }] #
switch [EXPR;] [EXPR2] { #Execute first case where EXPR2 == any EXPR3
[default|case EXPR3,...: #EXPR2 defaults to true
[...] #Cases are indentation-based
[fallthrough]] #Cases "break" by default.
... #Using fallthrough as last statement in a case continues to next case
} #Cannot be done in last case.
for [EXPR]; [BOOL_EXPR]; [EXPR2] #For loop
{ ... } #BOOL_EXPR defaults to true
for [BOOL_EXPR] { ... } #Same as for ; [BOOL_EXPR]; { ... }
#I.e. while loop
for KEY_VAR[, VAL_VAR2] #Iterates
:= range STR|MAP|[*]ARR|SLICE #For STR:
{ ... } # - KEY is byte position INT, but iteration is Unicode codepoint-wise
# - VAL is RUNE
#For ARR|SLICE: KEY is INT
#For MAP: iteration is unordered
for ... = range ... #Same but with already declared KEY_VAR, VAL_VAR
LABEL: EXPR #
break [LABEL] #Stops switch|for|select current block
#If LABEL, block labeled by it instead
continue [LABEL] #Stops for loop's current iteration
#If LABEL, block labeled by it instead
goto LABEL #Jump to LABEL
#Must be same FUNC and same|parent block
#If forward jump, must not skip over any VAR declaration
┌──────────┐
│ TYPE │
└──────────┘
NESTING ==> #All non-simple types can be nested: **TYPE, [][]TYPE, map[TYPE]map[TYPE2]TYPE3, etc.,
#including mixed
INLINE INFERING ==> #When instantiating MAP|ARR|SLICE (not STRUCT) inline {...}, TYPE in nested inline {...} can be omitted.
# - including nested []TYPE or *TYPE
#For example []TYPE{*TYPE2{...}} -> []TYPE{{...}}
SIMPLE VS COMPOSITE ==> #Simple types: BOOL, [U]INT|FLOAT|COMPLEX, RUNE|STR
#Composite types: *TYPE, FUNC, INTERFACE|STRUCT|MAP|ARR|SLICE, CHAN
VALUE-LIKE VS POINTER-LIKE ==> #Types are either:
# - value-like: simple (BOOL|[U]INT|FLOAT|COMPLEX|RUNE|STR) or STRUCT|ARR
# - zero-value: type-specific actual value
# - for composite types (STRUCT|ARR): empty, and recursive zero-value
# - passed|returned to|from FUNC by deep copy
# - including range return value, and INTERFACE <-> TYPE transtyping
# - pointer-like: *TYPE|FUNC|INTERFACE|MAP|SLICE|CHAN
# - zero-value: nil
# - passed|returned to|from FUNC by reference
# - actually by copy, but since they copy the underlying pointer, behaves like reference
type TYPE = TYPE2
type (TYPE = TYPE2;...) #Type alias
type TYPE TYPE2
type (TYPE TYPE2;...) #Type definition
┌───────────────┐
│ TRANSTYPE │
└───────────────┘
UNDERLYING TYPE ==> #TYPE after type resolution. Used on:
# - operators (like + .VAR (...) ...)
# - untyped constant type inference
#For assignments (= and function calls), transtype rules are used instead.
TYPE IDENTITY ==> #Identical TYPEs do not require transtyping.
#Identical if:
# - deeply equal TYPE, either simple|composite
# - type alias
#Not identical if:
# - type definition
#Must be exactly same:
# - including:
# - FUNC number|type of arguments|return values
# - FUNC receiver
# - STRUCT number|name|types|tags of properties
# - STRUCT order of properties
# - ARR size
# - excluding:
# - FUNC parameter|return VAR names
# - INTERFACE order of properties
IMPLICIT TRANSTYPE ==> #Not needed for identical TYPEs.
#For type definition (type TYPE TYPE2):
# - TYPE inherits allowed transtypes from TYPE2
# - If TYPE2:
# - literal|composite: can transtype TYPE <-> TYPE2
# - type name: cannot transtype TYPE <-> TYPE2
# - but if builtin simple type name: can transtype to untyped constant, with underlying TYPE2
#Example:
# type A int // A </> int A <=> 5
# type B A // B </> A|int B <=> int
# type C []A // C </> []int C <=> []A
# type D C // D </> C|[]int D <=> []A
TYPE(VAL) #Explicit transtype.
#The only ones allowed are the following.
(TYPE)(VAL) #Needs () when TYPE starts with * <- func
TYPE -> TYPE2 #When either:
# - used type definition (using type names)
# - same STRUCT except tags
NUM -> other NUM #Not if:
# - COMPLEX with imaginary part -> [U]INT|FLOAT
#Precision loss allowed, but only if var VAR (not CONST_VAL):
# - FLOAT with decimal -> [U]INT (truncated towards 0)
# - NUM -> less precise NUM (rounded)
# - too high NUM -> smaller NUM (overflows)
# - negative NUM -> UINT (overflows)
UINT32|RUNE -> STR
[]UINT32|[]RUNE <-> STR #Using Unicode codepoint
CHAN -> other CHAN #Only if does not lose receiver|sender direction.
#I.e. CHAN to CHAN<-, CHAN to <-CHAN, but not inverse.
┌────────────────┐
│ ASSIGNMENT │
└────────────────┘
SCOPE ==> #Block-scoped:
# - "universe":
# - pre-defined language: builtin TYPE|FUNC, true|false|iota|nil
# - package:
# - any top-level declaration, except import
# - shared by all files of same package
# - file:
# - import statements only
# - shared only within same file
# - function
# - statement
# - including if|for|case
# - if|for|switch first optional EXPR is scoped within following block
#Inherit parent scope, but not children
# - including in anomymous FUNC ("closure")
#Cannot redeclare in same scope, but can in children ("shadowing")
#Method's scope (unlike FUNC) is same as receiver's
#type TYPE [=] TYPE2 can be in function|statement scope
_ #Special VAR name ("blank identifier").
#Can only be declared. Value cannot be used.
#VAR name is not checked for uniqueness, i.e. can be declared several times without conflict.
#Not checked in STRUCT == STRUCT2
#Not allowed in INTERFACE
ZERO-VALUE ==> #Default value when no assigned value (including nil, e.g. with new())
INITIALIZED VALUE ==> #First assigned value (including empty, e.g. with make()).
VAL,... #Multiple values (MVAL)
#Similar to array, except must be stored in one variable each
#Evaluated together, before what they assigned to
# - e.g. can swap using a, b = b, a
var VAR,... TYPE
var (VAR,... TYPE;...) #Declare + assign zero-value
VAR = VAL
VAR,... = MVAL #Assign
var VAR [TYPE] = VAL #Declare + assign
var (VAR [TYPE] = VAL;...) #Infers TYPE from value:
var VAR,... [TYPE] = MVAL # - for NUM:
var (VAR,... [TYPE] = MVAL;...) # - complex128 if imaginary part
# - float64 if decimal part
# - int otherwise
# - cannot be nil
VAR := VAL #Shortcut syntax for var VAR = VAL, except:
VAR,... := MVAL # - can be in if|for|switch first optional EXPR
# - cannot be in top-level scope
CONST_VAL #Value evaluated at compile-time
#Restrictions:
# - only simple types, not composite
# - not Math.Inf|NaN()
# - only literals or const VAR
# - not var VAR
# - operators, TYPE(), builtin FUNC imag|real|complex|len|cap(), unsafe.Sizeof|Offsetof|Alignof()
# - not other FUNC()
#If not typed at declaration-time, "untyped constant". Becomes typed when:
# - needs type through type inference
# - e.g. passed as argument|operand or assigned to var VAR
# - but not when passed to another const VAR
# - explicitely transtyped (TYPE())
const ... #Like var ... but CONST_VAL
#Cannot be re-assigned.
#VAL must be specified. Exception:
# - if:
# - inside const (...), and not first declaration
# - TYPE omitted as well
# - then defaults to previous statement's VAL (including iota)
iota #Current const-declaration index (start at 0) inside const (...)
#Used for enums
VAR += -= *= /= %= VAL
VAR |= ^= &= &^= <<= >>= VAL #Like VAR = VAR OP VAL2
VAR++
VAR-- #Like VAR = VAR +|- 1. Statement, not EXPR
┌──────────────┐
│ FUNCTION │
└──────────────┘
func FUNC([VAR] [TYPE],...) #Function declaration
[TYPE2|([VAR2] [TYPE2],...)] #TYPE|TYPE2 defaults to the next one
{ ... } #If VAR omitted:
# - all other VAR must be omitted
# - cannot refer to any arguments
#TYPE2 is return type
# - TYPE,... is when returning MVAL
# - if second is BOOL, often named "ok" ("comma ok")
# - if named (VAR2): declare the variable on top of function
#TYPE can be variadic ...TYPE, i.e. 0-n arguments:
# - must be last
# - is a []TYPE
# - called with FUNC([MVAL]) or FUNC(SLICE...)
# - if no arguments:
# - no MVAL arguments: nil
# - empty SLICE... argument: empty SLICE
#{ ... } can be omitted if FUNC is declared in C|ASM
nil #Zero-value
#Cannot call
func(...) [...] {...} #Anonymous function (no FUNC name)
#Same as function declaration except:
# - can be used as value
# - can be declared inside another FUNC
# - cannot be a method
#Higher operator priority than FUNC(), i.e. can do func(...) {...}(...)
func(...) [...] #Function TYPE
#I.e. anonymous functions can be used as FUNC arguments
#Receiver is not part of function TYPE
return [MVAL] #Required when there is a return TYPE2. Optional otherwise.
#If any return value is named (VAR2), MVAL defaults to them ("naked return"):
# - if mixed with unnamed, those use their zero-value
FUNC([MVAL]) #Call a function
FUNC(FUNC2(...)->MVAL) #If FUNC2 returns MVAL, can pass as arguments directly
PRE-DEFINED FUNC ==> #Like len(), cap(), etc. can only be used in FUNC calls, not as value
┌──────────┐
│ BOOL │
└──────────┘
bool #TYPE
#Zero value is false
true|false #BOOL
!BOOL
BOOL && BOOL2
BOOL || BOOL2 #
VAL == != VAL2 #Allowed:
# - BOOL, NUM, STR
# - *TYPE: same reference
# - INTERFACE: use dynamic type
# - STRUCT|ARR: deep equal
# - CHAN: same instance
#Not allowed:
# - FUNC|MAP|SLICE (except against nil)
#If cannot transtype VAL <-> VAL2, panic.
# - including STRUCT number|name|types|tags|order of properties
VAL < <= > >= VAL2 #Only for:
# - NUM (except COMPLEX)
# - STR: lexically byte-wise
#If cannot transtype VAL <-> VAL2, panic.
┌─────────────┐
│ INTEGER │
└─────────────┘
[u]int8|16|32|64 #TYPE with 8|16|32|64 bits
#Zero value is 0 (same for others)
[u]int #TYPE with 32|64 bits depending on OS
byte #Alias for uint8, meant for binary data
N... #[U]INT
0bN...
0BN...
0oN...
0ON...
0xN...
0XN... #2|8|16 bases
[U]INT / [U]INT2 #Integer division
[U]INT % [U]INT2 #Integer remainder
^[U]INT #Invert bits
[U]INT & | ^ &^ [U]INT2 #Bitwise operations. &^ is same as NUM & ^NUM2
[U]INT << >> UINT2 #
┌───────────┐
│ FLOAT │
└───────────┘
float32|64 #TYPE with 32|64 bits
#Zero value is 0
[N...][.N...][e|E+|-N...] #FLOAT
0x[N...][.N...][p|P+|-N...]
0X[N...][.N...][p|P+|-N...] #0x... * 2**N (0x... is base16, N is base 10)
┌─────────────┐
│ COMPLEX │
└─────────────┘
complex64|128 #TYPE for complex numbers, with 64|128 bits
#Zero value is 0
INT|FLOATi
INT|FLOAT2 [+|- INT|FLOATi] #COMPLEX
real(COMPLEX)->INT|FLOAT2
imag(COMPLEX)->INT|FLOATi
complex(INT|FLOAT2, +|-INT|FLOATi)
->COMPLEX #
┌────────────┐
│ NUMBER │
└────────────┘
NUM #[U]INT|FLOAT|COMPLEX|RUNE|UINTPTR
UNDERSCORES ==> #Can appear to separate digits. Non-significant.
+NUM
-NUM #
NUM + - * / NUM2 #
┌──────────┐
│ RUNE │
└──────────┘
rune #TYPE. Single Unicode codepoint.
#Alias for int32, i.e. manipulated like integer codepoint.
#Cannot represent above \u10ffff, or \ud800-\udfff
#Zero-value is '\000'
'...' #RUNE
#Can contain Unicode characters as is, except unescaped '
#Single-line (no newline)
#Can also contain escape sequences:
# - \a \b \f \n \r \t
# - \XXX (base 8)
# - \xXX (base 16)
# - \uXXXX \UXXXXXXXX (Unicode codepoint)
# - \\ \'
┌────────────┐
│ STRING │
└────────────┘
string #TYPE
#Zero-value is ""
#Immutable: STR operations create a new STR2
"..." #STR
#Can contain Unicode characters, except unescaped "
#Single-line (no newline)
#Contain same escape sequences as RUNE
`...` #STR
#Can contain Unicode characters, except `
#Multi-line (can include newline)
# - raw \r are discarded
#Cannot contain escape sequences (\ has no special meaning)
STR + STR2 #Concatenation
STR[UINT] #Get RUNE
#Cannot set
STR[[UINT]:[UINT2]] #Same behavior as SLICE[...:...], but creates a new STR2.
len(STR)->UINT #Size, in byte (not character)
┌─────────────┐
│ POINTER │
└─────────────┘
*TYPE #TYPE2. Pointer of a TYPE.
#Used to pass a VAR by reference instead of value
#Lower operator priority than [UINT] or .VAR
nil #Zero-value of any *TYPE
&VAR
&ARR|SLICE[UINT]
&STRUCT.VAR #Generate a pointer (TYPE -> *TYPE)
&TYPE{...} #Not allowed: &MAP[KVAL]
*POINTER #Dereference a pointer (*TYPE -> TYPE)
STRUCT.VAR #Same as (*STRUCT).VAR
POINTER.METHOD(...) #Same as (*POINTER).METHOD(...) when using a non-POINTER_TYPE receiver
VAL.METHOD(...) #Same as (&VAL).METHOD when using a POINTER_TYPE receiver
#Not if VAL is INTERFACE|MAP
ARR_POINTER[...[:...[:...]]] #Same as (*ARR_POINTER)[...[:...[:...]]]
new(TYPE) #Same as:
# var VAR TYPE (assigning zero-value)
# return &VAR
┌────────────────────────┐
│ POINTER ARITHMETIC │
└────────────────────────┘
import "unsafe" #Not recommended, as memory layout assumption might not be portable
unsafe.Pointer #*TYPE with unknown value TYPE
# - cannot be deferenced
#Goal is to transtype *TYPE <-> UNSAFE_POINTER <-> UINTPTR
# - only explicit transtype
# - direct *TYPE <-> UINTPTR not allowed
uintptr #TYPE of a pointer's address.
#Like UNSAFE_POINTER, unknown underlying value type.
#Unlike *TYPE|UNSAFE_POINTER, represents the address itself, not the value referenced by that address.
#*TYPE|UNSAFE_POINTER|UINPTR do not error if address points at non-accessible|allocated|aligned value
# - however deferencing *TYPE will panic with SIGSEGV
#Does not keep reference of that value, i.e. might be garbage collected
# - need to transtype with unsafe.Pointer() in the same statement to ensure reference is kept
#Behaves like UINT:
# - including size and zero-value
#Goals:
# - pointer arithmetic with unsafe.Sizeof|Offsetof|Alignof()
# - TYPE -> TYPE2 transtype, using same underlying memory layout
# - printing address
#Some standard library use UINTPTR, e.g. syscall.Syscall() or reflect.ValueOf().Pointer|UnsafeAddr()
unsafe.Sizeof(VAL)->UINTPTR #Memory byte size:
# - BOOL: 1
# - [U]INT|UINTPTR|*TYPE: OS word size (8 on mine)
# - [U]INT8|16|32|64, FLOAT32|64, COMPLEX64|128, BYTE, RUNE: 1|2|4|8|16
# - STRUCT|ARR: sum of each element's TYPE
# - STR|INTERFACE|MAP|SLICE|CHAN: 2|2|1|3|1 pointers
unsafe.Offsetof(STRUCT.VAR) #Memory byte difference between &STRUCT and &STRUCT.VAR
->UINTPTR #Equals the sum of unsafe.Sizeof() of all STRUCT properties before STRUCT.VAR
unsafe.Alignof(VAL)->UINTPTR #Memory alignment byte size:
# - NUM|BOOL: same as unsafe.SizeOf()
# - COMPLEX64|128: 4|8
# - STRUCT|ARR: max of any element TYPE
# - STR|INTERFACE|MAP|SLICE|CHAN: 1 pointer
#Means this value's address % ALIGNMENT must be 0
┌────────────┐
│ STRUCT │
└────────────┘
struct #STRUCT_TYPE
{ [[VAR,...] TYPE [STR]];... } #Ordered object whose keys are names and values any TYPE.
#If VAR omitted ("embedded field"):
# - default name is "TYPE"
# - if PACKAGE.TYPE, only "TYPE"
# - TYPE must be type name, not type literal
# - can be *TYPE
# - if TYPE is STRUCT_TYPE|INTERFACE_TYPE, can access TYPE.* directly from STRUCT_TYPE.* ("promoted field")
# - not in literal STRUCT_TYPE{...}
# - if parent TYPE can have same property, parent property shadows it
# - also add its "method set"
#STR is "tag":
# - no semantics but:
# - can be retrieved with reflect PACKAGE
# - part of TYPE identity
# - usually `VAR:"STR" ...`
# - default: ``
EMPTY STRUCT ==> #Zero-value, i.e. each element uses its own zero-value
#No nil
STRUCT_TYPE{ [[VAR:] VAL],... } #Creates a new STRUCT, instance of STRUCT_TYPE
#If VAR, named, otherwise positional. Cannot mix.
# - positional not recommended when using another package, as that package might change
# fields order without considering it a breaking change
#VAL defaults to zero-value
# - if positional, only if all VAL omitted
STRUCT.VAR [= VAL] #Get|set property
┌───────────────┐
│ INTERFACE │
└───────────────┘
func ([VAR3] RECEIVER_TYPE) #Method declaration.
FUNC(...) ... {...} #Function with special argument VAR3 ("receiver") similar to "this" in other languages.
#RECEIVER_TYPE:
# - must be a defined type (type TYPE TYPE2)
# - type name must be defined in same package
# - must not be INTERFACE_TYPE
#Same FUNC can be re-declared with different receivers (including none)
# - including with different parameter|return types|number (but not very useful)
#"Method set" is all methods of a specific receiver.
# - inherited by identical types only
# - i.e. not by "type TYPE TYPE2"
VAR3.FUNC(...) #Method value|call
RECEIVER_TYPE.FUNC(VAR3, ...)
(*RECEIVER_TYPE).FUNC(*VAR3, ...)
INTERFACE_TYPE.FUNC(INTERFAC, ...)#Method expression. Same as VAR3.FUNC but FUNC type's first argument is of RECEIVER_TYPE
VAR3.FUNC
RECEIVER_TYPE.FUNC
(*RECEIVER_TYPE).FUNC
INTERFACE_TYPE.FUNC #Same, but only retrieving the function value. Can be used for binding.
interface { #INTERFACE_TYPE
[FUNC(...) [...]];... #FUNC(...) [...] syntax is like FUNC_TYPE but with a function name
[INTERFACE_TYPE2];... #If INTERFACE_TYPE2, include its methods ("embedded")
} # - if some methods already exists, must exactly match
# - cannot embed itself (including recursively)
#Recommended names
# - if INTERFACE single FUNC (e.g. Write()) -> "FUNCer" (e.g. Writer)
# - if FUNC is meant for transtyping to TYPE -> "Type()" (not ToType())
interface {} #Empty INTERFACE can be used to describe "any TYPE"
nil #Zero-value
#Unlike empty INTERFACE:
# - cannot call any method
#Means there is no underlying value, i.e.:
# - if underlying value is nil itself, INTERFACE is not
# - when a FUNC returns INTERFACE|nil, it should not return TYPE(nil) (where TYPE is transtypable to INTERFACE)
# - otherwise caller would received transtyped INTERFACE, not nil
TRANSTYPE ==> #Any TYPE can transtype to INTERFACE_TYPE providing it includes at least the same methods ("method set")
# - methods order is not significant
# - it wraps the underlying TYPE ("dynamic type"), i.e. acting as an abstraction type ("static type")
# - only INTERFACE.METHOD(...) can be used, unless transtyped to underlying TYPE
#Even if TYPE <-> INTERFACE_TYPE, cannot []TYPE <-> []INTERFACE_TYPE
# - must transtype each element individually instead
INTERFACE.(TYPE) #Transtype back to underlying TYPE ("type assertion")
#Must be used instead of TYPE(INTERFACE)
#Returns MVAL of VAL, BOOL
#BOOL is whether VAL has exact same underlying TYPE
# - if not, panic unless BOOL was retrieved (i.e. can be used for asserting)
# - in which case VAL will be zero-value
switch #"Type switch": like normal switch except:
[EXPR;] [VAR :=] INTERFACE.(type)# - value is TYPE|nil
{ ... } # - no fallthrough
INTERFACE.NOOP() #INTERFACE transtype is by structure (same interface methods), not by name (same interface TYPE).
#To make it by name, can use a noop function with a unique function name.
#Try to avoid.
RETURN INTERFACE VS TYPE ==> #It is better for a FUNC return type to be INTERFACE_TYPE than the underlying TYPE2, because
#it restricts what's exposed to the caller
# - e.g. FUNC()->error instead of FUNC()->os.PathError
┌─────────┐
│ MAP │
└─────────┘
map[KTYPE]VTYPE #MAP_TYPE
#Unordered object whose keys are KTYPE and values are VTYPE
#KTYPE must allow ==, i.e. cannot be FUNC|MAP|SLICE
nil #Zero-value.
#Like empty MAP:
# - can get (returns zero-value)
# - can delete
# - length is 0
#Unlike empty MAP:
# - cannot set
make(map[KTYPE]VTYPE[, UINT])->MAP#Creates an empty MAP.
#Pre-allocates space for UINT elements
# - only for performance optimization. Size grows dynamically.
map[KTYPE]VTYPE{ [VAL: VAL2],... }#Creates a MAP with some elements
MAP[KVAL] #Get an element.
#Return VAL, BOOL:
# - if element not found, VAL is zero-value and BOOL is false
MAP[KVAL] = VAL #Set an element
delete(MAP, KVAL) #Delete an element
len(MAP)->UINT #Number of keys
┌───────────┐
│ ARRAY │
└───────────┘
[UINT]TYPE #ARR_TYPE
#UINT is static size.
# - can be an EXPR
#Prefer SLICE if possible
EMPTY ARR ==> #Zero-value, i.e. each element uses its own zero-value
#No nil
[UINT]TYPE{[[INDEX:] VAL],...} #Creates a new ARR
#VAL defaults to zero-value
#INDEX defaults to last INDEX+1, or 0
[...]TYPE{[[INDEX:] VAL],...} #Same but guesses UINT
ARR[UINT] [= VAL] #Get|set element
#Error if out-of-bound
len(ARR)->UINT #Number of elements
cap(ARR)->UINT #Same
┌───────────┐
│ SLICE │
└───────────┘
[]TYPE #SLICE_TYPE
#Reference to part of an ARR
#No static size
#Cannot transtype from|to ARR
nil #Zero-value.
#Like empty SLICE:
# - has 0 length|capacity
# - can be read|sliced
# - can be manipulated by copy|append(), behaving like an empty SLICE
#Unlike empty SLICE:
# - has no underlying ARR
# - SLICE[...:...[:...]] returns another nil
MEMORY EFFICIENCY ==> #Since it keeps whole ARR in memory but only use a subset, it is more memory efficient,
#but less CPU efficient, to create a new smaller ARR that fits the SLICE, so the bigger
#one can be garbage collected when function returns:
# sliceB := make([]TYPE, len(sliceA))
# copy(sliceB, sliceA)
make([]TYPE, UINT[, UINT2])->SLICE#Creates a new SLICE, including the underlying ARR, with zero-value elements.
#UINT is length, UINT2 is capacity (def: UINT)
[]TYPE{[[INDEX:] VAL],...} #Creates a new SLICE, including the underlying ARR, with specific elements
#Same INDEX|VAL default values as [UINT]TYPE{...}
ARR[[UINT]:[UINT2][:UINT3]] #Creates a new SLICE from ARR[UINT] to ARR[UINT2 - 1]
#UINT3 is last element to allow in future slices, i.e. sets the capacity
#UINT defaults to 0, UINT2|UINT3 to len(ARR)
#Error if out-of-bound
SLICE[[UINT]:[UINT2][:UINT3]] #Creates a new SLICE2 from the underlying ARR
#UINT adds to SLICE's own UINT, i.e. can only go forward
#But UINT2 replaces SLICE's own UINT2, to change size
#Same with UINT3, to decrease capacity
#Error if out-of-bound
SLICE[UINT] [= VAL] #Like ARR
len(SLICE)->UINT #Number of elements of SLICE
cap(SLICE)->UINT2 #Number of elements of max-resized SLICE[:UINT2], i.e. number of elements of underlying ARR
#from same start UINT
copy(SLICE, SLICE2)->UINT #Copy UINT first elements of SLICE2 to SLICE's underlying ARR
copy([]BYTE, STR)->UINT #UINT is min(len(SLICE), len(SLICE2))
append(SLICE, VAL...)->SLICE2 #Write VAL,... to SLICE's underlying ARR, after SLICE end
append([]BYTE, STR...)->[]BYTE2 #If underlying ARR too small, creates a new one, and write to it instead
#Return new SLICE2 contains all original+new elements
#STR... uses spread "..."
┌───────────┐
│ ERROR │
└───────────┘
defer FUNC(...) #Call a function:
# - right after return statement evaluated
# - can access named return variables, set to their return value
# - or after function panicked
# - but before function returns
#Arguments are evaluated right away though.
#If anonymous FUNC, closure kept.
#Last defer is executed first.
#Purpose: like a try/catch/finally block.
panic(VAL) #Trigger a "panic": like throwing an exception in other languages
#Each parent's deferred FUNC is called in order.
#By convention VAL:
# - should not be nil, since it makes it confusing with recover()
# - should be ERROR or "MESSAGE"
#When reaching top-level:
# - aborts program
# - exit code 2
# - prints:
# - VAL
# - stack trace of each goroutine
# - if panic was recover()'d then re-panic(), include both original|new panic() in stack trace
# - independent from the panic VAL
recover()->VAL|nil #Stop current panic, and return the VAL passed to panic()
#Noop and returns nil if either:
# - no panic
# - not inside defer FUNC
error #INTERFACE_TYPE
#By convention:
# - ERROR_TYPE should be STRUCT|STR implementing this INTERFACE
# - ERROR_TYPE named *Error
# - ERROR named err or err*
ERROR.Error()->STR #Serialize an ERROR
ERROR.ERROR_TYPE() #Often used to differentiate INTERFACE_TYPE by error name
ERROR RETURN ==> #Returned as MVAL: VAL, ERROR|nil, to be tested by caller
#Preferred if recoverable or libraries
#Better for return type to be error, not specific ERROR_TYPE, because it restricts what's exposed
# - can still document ERROR_TYPE, and user can test type or transtype
#Should return nil (i.e. error(nil)), not specific ERROR_TYPE(nil)
# - because it would be transtyped to INTERFACE error, which would then not be nil
ERROR PANIC ==> #panic(ERROR)
#Preferred if neither recoverable nor libraries
runtime.Error #ERROR_INTERFACE_TYPE
#Panicked by language runtime errors, such as:
# - wrong operator for a given TYPE: STR.VAR, SLICE == SLICE2, ...
# - some operations on nil: *nil, nil(), close(nil), ...
# - out-of-bound: STR|ARR|SLICE[NUM], make(TYPE, -NUM)
# - arithmetic error: NUM / 0, NUM << -NUM2
# - invalid type assertion: VAL.(INTERFACE)
# - closed CHAN: CHAN <- VAL after close(CHAN)
RUNTIME_ERROR.RuntimeError() #
runtime.TypeAssertionError #RUNTIME_ERROR_TYPE for an invalid type assertion
FUNC()[->ERROR] #Means ->ERROR|nil
┌───────────────┐
│ GOROUTINE │
└───────────────┘
go FUNC(...) #Call a function but inside a new goroutine.
#Arguments are evaluated in the current goroutine though.
GOROUTINE ==> #Like coroutine:
# - run concurrently
# - based on co-operative scheduling (CHAN)
# - can share process memory|scope
# - consume less CPU and memory than processes
#However:
# - use OS threads under hood, unlike usual coroutines which are fully userland
# - i.e. benefits from OS scheduling and multi-core parallelism
#Use a threads pool:
# - each time goroutine yields, return thread to pool
# - yield on:
# - CHAN<- or <-CHAN
# - runtime.Gosched()
# - pre-emptively, i.e. in-between two safe statements, after the goroutine has run for some time
# - when continue, take thread from pool
runtime.Gosched() #Make current goroutine yield.
#I.e. allow other goroutines to use CPU before starting again.
EXIT ==> #Process (main goroutine) exit terminates threads
# - does not wait for their exit
# - can use synchronization to wait
runtime.Goexit() #Stops current goroutine. Other goroutines keep running.
#Does not trigger a panic.
# - deferred FUNCs are called, but recover() returns nil
#If main goroutine:
# - wait for all goroutines to exit
# - then crash (exit code 1, print stack trace)
runtime.LockOSThread() #Ensure goroutine always re-use the same thread
#Can be done several times, requiring several call to UnlockOSThread() to undo
#Only useful when using C|ASM to use thread-specific memory (e.g. errno)
runtime.UnlockOSThread() #Inverse
runtime.NumGoroutine()->INT #Number of running goroutines
SHARED MEMORY ==> #All goroutines from same package share package scope.
#Also, if FUNC is closure, still holds reference to upper scopes.
COLLISION ==> #Can happen due to shared memory between goroutines.
INSTRUCTIONS RE-ORDERING ==> #Compiler might also re-order instructions when this would not impact behavior within same goroutine
# - even if it might impact other goroutines accessing shared memory
#For example: a = 1; b = 2;
# - second statement might be run before first since that does not change the current goroutine
# - so if another goroutine should not assume that if b == 2, then a == 1
SYNCHRONIZATION ==> #See concurrency doc.
#Common synchronization patterns in Go (in preference order):
# - avoiding shared resources
# - CHAN send|receive is guaranteed to be in order
# - "sync" and "sync/atomic" packages
#Note: nothing is ever re-ordered before|after a go FUNC() statement
MAPS ==> #MAP[KVAL] = VAL is not atomic.
#I.e. one goroutine might read it while it is being half-written by another one
# - i.e. not a problem if read-only, or write-only (single writer)
#However sync.map is atomic
┌─────────────┐
│ CHANNEL │
└─────────────┘
chan TYPE #CHAN_TYPE.
#Pipe|FIFO with TYPE elements, meant for cross-goroutine communication
chan <- TYPE
<- chan TYPE #Same but only allows sending or receiving
nil #Zero-value.
#Receive|send block forever.
#Length|capacity is 0
make(chan TYPE[, UINT])->CHAN #Creates a CHAN instance
#UINT is buffer size (def: 0, i.e. unbuffered|sync)
CHAN <- VAL #Send VAL to CHAN (push).
#If unbuffered, blocks until it gets received.
#If buffered and buffer full, blocks until it can push.
<-CHAN #Receive VAL from CHAN (pop).
#Blocks until a VAL is available
#Returns VAL, BOOL
# - BOOL is whether CHAN was closed
# - if CHAN closed, panic unless BOOL was retrieved
close(CHAN) #Cannot send anymore, but can still receive:
# - send panics
# - receive:
# - works for any buffered VAL
# - then receive returns VAL, true, where VAL is CHAN's TYPE zero-value
#Panic if CHAN is either receive-only, or nil
#Automatically done at end of process. Only necessary when either:
# - using for VAL := range CHAN
# - want to forbid send
for VAL := range CHAN { ... } #Iterates unless CHAN closed
select {
[case EXPR:
...]... #All EXPR must be CHAN <- VAL or [VAR[, BOOL] =|:=] <-CHAN:
[default: #A random case is executed
...] # - only among CHAN <- VAL ready to send, or <-CHAN ready to receive
# - default block is only run if none ready
} #Similar syntax than switch, except no fallthrough and only one EXPR per case.
for { select { ... } } #Usually put in an infinite loop, and using return to exit
len(CHAN)->UINT #Number of buffered elements
cap(CHAN)->UINT #Buffered size
┌───────────┐
│ PRINT │
└───────────┘
print[ln](VAL,...) #Prints on stderr, space|newline-separated
#Somewhat deprecated. Does not support printing STRUCT. Not great output.
#Prefer fmt.Print[ln]().
┌─────────────┐
│ PACKAGE │
└─────────────┘
package PACKAGE #Declare:
# - which PACKAGE file belongs to
# - package's default import VAR
#Must be first statement
#All *.go within same DIR must have same PACKAGE
#Recommended lowercase
package main #CLI entry point (as opposed to programmatic)
#Must have a main FUNC
#By convention, filename is main.go
EXPORT ==> #Any top-level variable whose variable name starts with uppercase letter is exported
#Recommended not to namespace their variable name, since package already namespaces them
import [PACKAGE] "IMPORT_PATH" #Import package's exported variables PACKAGE.VAR ("qualified identifier").
import #Available as top-level variable PACKAGE:
([PACKAGE] "IMPORT_PATH";...) # - def: package PACKAGE
# - if _, meant only for side-effects
# - if ., make all exported variables available without any namespace
# - not recommended outside automated tests
#Waits for package to initialize
#Package cycles not allowed
#Idempotent: import is cached and side-effects are not redone
#Must be available in GOBIN
func init() { ... } #Called when file gets imported
#Meant for import-time side-effects
#Can be several per file|package
#Cannot refer to it as FUNC call|value
INITIALIZATION ORDER ==> #If a top-level declaration depends on another inside same package, it waits for it
# - even if different file
# - even if before it in line order
#Package initialization order:
# - import statements
# - package scope declarations
# - init()
#Within same initialization category, file-by-file:
# - order depends on how it was compiled:
# - FILE...: arguments order
# - DIR: filename alphabetical order