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