OSDN Git Service

Regular updates
[twpd/master.git] / go.md
1 ---
2 title: Go
3 layout: 2017/sheet
4 prism_languages: [go, bash]
5 weight: -3
6 tags: [Featured]
7 category: C-like
8 updated: 2020-06-21
9 ---
10
11 ## Getting started
12 {: .-three-column}
13
14 ### Introduction
15 {: .-intro}
16
17 - [A tour of Go](https://tour.golang.org/welcome/1) _(tour.golang.org)_
18 - [Go repl](https://repl.it/languages/go) _(repl.it)_
19 - [Golang wiki](https://github.com/golang/go/wiki/) _(github.com)_
20
21 ### Hello world
22 {: .-prime}
23
24 #### hello.go
25 {: .-file}
26
27 ```go
28 package main
29
30 import "fmt"
31
32 func main() {
33   message := greetMe("world")
34   fmt.Println(message)
35 }
36
37 func greetMe(name string) string {
38   return "Hello, " + name + "!"
39 }
40 ```
41
42 ```bash
43 $ go build
44 ```
45
46 Or try it out in the [Go repl](https://repl.it/languages/go), or [A Tour of Go](https://tour.golang.org/welcome/1).
47
48 ### Variables
49
50 #### Variable declaration
51
52 ```go
53 var msg string
54 var msg = "Hello, world!"
55 var msg string = "Hello, world!"
56 var x, y int
57 var x, y int = 1, 2
58 var x, msg = 1, "Hello, world!"
59 msg = "Hello"
60 ```
61
62 #### Declaration list
63
64 ``` go
65 var (
66   x int
67   y = 20
68   z int = 30
69   d, e = 40, "Hello"
70   f, g string
71 )
72 ```
73
74 #### Shortcut of above (Infers type)
75
76 ```go
77 msg := "Hello"
78 x, msg := 1, "Hello"
79 ```
80
81 ### Constants
82
83 ```go
84 const Phi = 1.618
85 const Size int64 = 1024
86 const x, y = 1, 2
87 const (
88   Pi = 3.14
89   E  = 2.718
90 )
91 const (
92   Sunday = iota
93   Monday
94   Tuesday
95   Wednesday
96   Thursday
97   Friday
98   Saturday
99 )
100 ```
101
102 Constants can be character, string, boolean, or numeric values.
103
104 See: [Constants](https://tour.golang.org/basics/15)
105
106 ## Basic types
107 {: .-three-column}
108
109 ### Strings
110
111 ```go
112 str := "Hello"
113 ```
114
115 ```go
116 str := `Multiline
117 string`
118 ```
119
120 Strings are of type `string`.
121
122 ### Numbers
123
124 #### Typical types
125
126 ```go
127 num := 3          // int
128 num := 3.         // float64
129 num := 3 + 4i     // complex128
130 num := byte('a')  // byte (alias for uint8)
131 ```
132
133 #### Other types
134
135 ```go
136 var u uint = 7        // uint (unsigned)
137 var p float32 = 22.7  // 32-bit float
138 ```
139
140 ### Arrays
141
142 ```go
143 // var numbers [5]int
144 numbers := [...]int{0, 0, 0, 0, 0}
145 ```
146
147 Arrays have a fixed size.
148
149 ### Slices
150
151 ```go
152 slice := []int{2, 3, 4}
153 ```
154
155 ```go
156 slice := []byte("Hello")
157 ```
158
159 Slices have a dynamic size, unlike arrays.
160
161 ### Pointers
162
163 ```go
164 func main () {
165   b := *getPointer()
166   fmt.Println("Value is", b)
167 }
168 ```
169 {: data-line="2"}
170
171 ```go
172 func getPointer () (myPointer *int) {
173   a := 234
174   return &a
175 }
176 ```
177 {: data-line="3"}
178
179 ```go
180 a := new(int)
181 *a = 234
182 ```
183 {: data-line="2"}
184
185 Pointers point to a memory location of a variable. Go is fully garbage-collected.
186
187 See: [Pointers](https://tour.golang.org/moretypes/1)
188
189 ### Type conversions
190
191 ```go
192 i := 2
193 f := float64(i)
194 u := uint(i)
195 ```
196
197 See: [Type conversions](https://tour.golang.org/basics/13)
198
199 ## Flow control
200 {: .-three-column}
201
202 ### Conditional
203
204 ```go
205 if day == "sunday" || day == "saturday" {
206   rest()
207 } else if day == "monday" && isTired() {
208   groan()
209 } else {
210   work()
211 }
212 ```
213 {: data-line="1,3,5"}
214
215 See: [If](https://tour.golang.org/flowcontrol/5)
216
217 ### Statements in if
218
219 ```go
220 if _, err := doThing(); err != nil {
221   fmt.Println("Uh oh")
222 }
223 ```
224 {: data-line="1"}
225
226 A condition in an `if` statement can be preceded with a statement before a `;`. Variables declared by the statement are only in scope until the end of the `if`.
227
228 See: [If with a short statement](https://tour.golang.org/flowcontrol/6)
229
230 ### Switch
231
232 ```go
233 switch day {
234   case "sunday":
235     // cases don't "fall through" by default!
236     fallthrough
237
238   case "saturday":
239     rest()
240
241   default:
242     work()
243 }
244 ```
245
246 See: [Switch](https://github.com/golang/go/wiki/Switch)
247
248 ### For loop
249
250 ```go
251 for count := 0; count <= 10; count++ {
252   fmt.Println("My counter is at", count)
253 }
254 ```
255
256 See: [For loops](https://tour.golang.org/flowcontrol/1)
257
258 ### For-Range loop
259
260 ```go
261 entry := []string{"Jack","John","Jones"}
262 for i, val := range entry {
263   fmt.Printf("At position %d, the character %s is present\n", i, val)
264 }
265 ```
266
267 See: [For-Range loops](https://gobyexample.com/range)
268
269 ### While loop
270
271 ```go
272 n := 0
273 x := 42
274 for n != x {
275   n := guess()
276 }
277 ```
278
279 See: [Go's "while"](https://tour.golang.org/flowcontrol/3)
280
281 ## Functions
282 {: .-three-column}
283
284 ### Lambdas
285
286 ```go
287 myfunc := func() bool {
288   return x > 10000
289 }
290 ```
291 {: data-line="1"}
292
293 Functions are first class objects.
294
295 ### Multiple return types
296
297 ```go
298 a, b := getMessage()
299 ```
300
301 ```go
302 func getMessage() (a string, b string) {
303   return "Hello", "World"
304 }
305 ```
306 {: data-line="2"}
307
308
309 ### Named return values
310
311 ```go
312 func split(sum int) (x, y int) {
313   x = sum * 4 / 9
314   y = sum - x
315   return
316 }
317 ```
318 {: data-line="4"}
319
320 By defining the return value names in the signature, a `return` (no args) will return variables with those names.
321
322 See: [Named return values](https://tour.golang.org/basics/7)
323
324 ## Packages
325 {: .-three-column}
326
327 ### Importing
328
329 ```go
330 import "fmt"
331 import "math/rand"
332 ```
333
334 ```go
335 import (
336   "fmt"        // gives fmt.Println
337   "math/rand"  // gives rand.Intn
338 )
339 ```
340
341 Both are the same.
342
343 See: [Importing](https://tour.golang.org/basics/1)
344
345 ### Aliases
346
347 ```go
348 import r "math/rand"
349 ```
350 {: data-line="1"}
351
352 ```go
353 r.Intn()
354 ```
355
356 ### Exporting names
357
358 ```go
359 func Hello () {
360   ยทยทยท
361 }
362 ```
363
364 Exported names begin with capital letters.
365
366 See: [Exported names](https://tour.golang.org/basics/3)
367
368 ### Packages
369
370 ```go
371 package hello
372 ```
373
374 Every package file has to start with `package`.
375
376 ## Concurrency
377 {: .-three-column}
378
379 ### Goroutines
380
381 ```go
382 func main() {
383   // A "channel"
384   ch := make(chan string)
385
386   // Start concurrent routines
387   go push("Moe", ch)
388   go push("Larry", ch)
389   go push("Curly", ch)
390
391   // Read 3 results
392   // (Since our goroutines are concurrent,
393   // the order isn't guaranteed!)
394   fmt.Println(<-ch, <-ch, <-ch)
395 }
396 ```
397 {: data-line="3,6,7,8,13"}
398
399 ```go
400 func push(name string, ch chan string) {
401   msg := "Hey, " + name
402   ch <- msg
403 }
404 ```
405 {: data-line="3"}
406
407 Channels are concurrency-safe communication objects, used in goroutines.
408
409 See: [Goroutines](https://tour.golang.org/concurrency/1), [Channels](https://tour.golang.org/concurrency/2)
410
411 ### Buffered channels
412
413 ```go
414 ch := make(chan int, 2)
415 ch <- 1
416 ch <- 2
417 ch <- 3
418 // fatal error:
419 // all goroutines are asleep - deadlock!
420 ```
421 {: data-line="1"}
422
423 Buffered channels limit the amount of messages it can keep.
424
425 See: [Buffered channels](https://tour.golang.org/concurrency/3)
426
427 ### Closing channels
428
429 #### Closes a channel
430
431 ```go
432 ch <- 1
433 ch <- 2
434 ch <- 3
435 close(ch)
436 ```
437 {: data-line="4"}
438
439 #### Iterates across a channel until its closed
440
441 ```go
442 for i := range ch {
443   ยทยทยท
444 }
445 ```
446 {: data-line="1"}
447
448 #### Closed if `ok == false`
449
450 ```go
451 v, ok := <- ch
452 ```
453
454 See: [Range and close](https://tour.golang.org/concurrency/4)
455
456 ### WaitGroup
457
458 ```go
459 import "sync"
460
461 func main() {
462   var wg sync.WaitGroup
463   
464   for _, item := range itemList {
465     // Increment WaitGroup Counter
466     wg.Add(1)
467     go doOperation(&wg, item)
468   }
469   // Wait for goroutines to finish
470   wg.Wait()
471   
472 }
473 ```
474 {: data-line="1,4,8,12"}
475
476 ```go
477 func doOperation(wg *sync.WaitGroup, item string) {
478   defer wg.Done()
479   // do operation on item
480   // ...
481 }
482 ```
483 {: data-line="2"}
484
485 A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. The goroutine calls `wg.Done()` when it finishes.
486 See: [WaitGroup](https://golang.org/pkg/sync/#WaitGroup)
487
488
489 ## Error control
490
491 ### Defer
492
493 ```go
494 func main() {
495   defer fmt.Println("Done")
496   fmt.Println("Working...")
497 }
498 ```
499 {: data-line="2"}
500
501 Defers running a function until the surrounding function returns.
502 The arguments are evaluated immediately, but the function call is not ran until later.
503
504 See: [Defer, panic and recover](https://blog.golang.org/defer-panic-and-recover)
505
506 ### Deferring functions
507
508 ```go
509 func main() {
510   defer func() {
511     fmt.Println("Done")
512   }()
513   fmt.Println("Working...")
514 }
515 ```
516 {: data-line="2,3,4"}
517
518 Lambdas are better suited for defer blocks.
519
520 ```go
521 func main() {
522   var d = int64(0)
523   defer func(d *int64) {
524     fmt.Printf("& %v Unix Sec\n", *d)
525   }(&d)
526   fmt.Print("Done ")
527   d = time.Now().Unix()
528 }
529 ```
530 {: data-line="3,4,5"}
531 The defer func uses current value of d, unless we use a pointer to get final value at end of main.
532
533 ## Structs
534 {: .-three-column}
535
536 ### Defining
537
538 ```go
539 type Vertex struct {
540   X int
541   Y int
542 }
543 ```
544 {: data-line="1,2,3,4"}
545
546 ```go
547 func main() {
548   v := Vertex{1, 2}
549   v.X = 4
550   fmt.Println(v.X, v.Y)
551 }
552 ```
553
554 See: [Structs](https://tour.golang.org/moretypes/2)
555
556 ### Literals
557
558 ```go
559 v := Vertex{X: 1, Y: 2}
560 ```
561
562 ```go
563 // Field names can be omitted
564 v := Vertex{1, 2}
565 ```
566
567 ```go
568 // Y is implicit
569 v := Vertex{X: 1}
570 ```
571
572 You can also put field names.
573
574 ### Pointers to structs
575
576 ```go
577 v := &Vertex{1, 2}
578 v.X = 2
579 ```
580
581 Doing `v.X` is the same as doing `(*v).X`, when `v` is a pointer.
582
583 ## Methods
584
585 ### Receivers
586
587 ```go
588 type Vertex struct {
589   X, Y float64
590 }
591 ```
592
593 ```go
594 func (v Vertex) Abs() float64 {
595   return math.Sqrt(v.X * v.X + v.Y * v.Y)
596 }
597 ```
598 {: data-line="1"}
599
600 ```go
601 v := Vertex{1, 2}
602 v.Abs()
603 ```
604
605 There are no classes, but you can define functions with _receivers_.
606
607 See: [Methods](https://tour.golang.org/methods/1)
608
609 ### Mutation
610
611 ```go
612 func (v *Vertex) Scale(f float64) {
613   v.X = v.X * f
614   v.Y = v.Y * f
615 }
616 ```
617 {: data-line="1"}
618
619 ```go
620 v := Vertex{6, 12}
621 v.Scale(0.5)
622 // `v` is updated
623 ```
624
625 By defining your receiver as a pointer (`*Vertex`), you can do mutations.
626
627 See: [Pointer receivers](https://tour.golang.org/methods/4)
628
629 ## Interfaces
630
631 ### A basic interface
632
633 ```go
634 type Shape interface {
635   Area() float64
636   Perimeter() float64
637 }
638 ```
639
640 ### Struct
641
642 ```go
643 type Rectangle struct {
644   Length, Width float64
645 }
646 ```
647
648 Struct `Rectangle` implicitly implements interface `Shape` by implementing all of its methods.
649
650 ### Methods
651
652 ```go
653 func (r Rectangle) Area() float64 {
654   return r.Length * r.Width
655 }
656
657 func (r Rectangle) Perimeter() float64 {
658   return 2 * (r.Length + r.Width)
659 }
660 ```
661
662 The methods defined in `Shape` are implemented in `Rectangle`.
663
664 ### Interface example
665
666 ```go
667 func main() {
668   var r Shape = Rectangle{Length: 3, Width: 4}
669   fmt.Printf("Type of r: %T, Area: %v, Perimeter: %v.", r, r.Area(), r.Perimeter())
670 }
671 ```
672
673 ## References
674
675 ### Official resources
676 {: .-intro}
677
678 - [A tour of Go](https://tour.golang.org/welcome/1) _(tour.golang.org)_
679 - [Golang wiki](https://github.com/golang/go/wiki/) _(github.com)_
680 - [Effective Go](https://golang.org/doc/effective_go.html) _(golang.org)_
681
682 ### Other links
683 {: .-intro}
684
685 - [Go by Example](https://gobyexample.com/) _(gobyexample.com)_
686 - [Awesome Go](https://awesome-go.com/) _(awesome-go.com)_
687 - [JustForFunc Youtube](https://www.youtube.com/channel/UC_BzFbxG2za3bp5NRRRXJSw) _(youtube.com)_
688 - [Style Guide](https://github.com/golang/go/wiki/CodeReviewComments) _(github.com)_