wip/go: add
This commit is contained in:
parent
43dd55e252
commit
db90135f2b
|
@ -0,0 +1,396 @@
|
||||||
|
---
|
||||||
|
title: Go
|
||||||
|
layout: 2017/sheet
|
||||||
|
prism_languages: [go, bash]
|
||||||
|
tags: [WIP]
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
{: .-three-column}
|
||||||
|
|
||||||
|
### Hello world
|
||||||
|
{: .-prime}
|
||||||
|
|
||||||
|
```go
|
||||||
|
// hello.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import ( "fmt" )
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
message := greetMe("world")
|
||||||
|
fmt.Println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func greetMe(name string) (string) {
|
||||||
|
return "Hello, " + name + "!"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go build
|
||||||
|
```
|
||||||
|
|
||||||
|
Or try it out in the [Go repl](https://repl.it/languages/go), or [A Tour of Go](https://tour.golang.org/welcome/1).
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Variable declaration
|
||||||
|
var msg string
|
||||||
|
msg = "Hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Shortcut of above (Infers type)
|
||||||
|
msg := "Hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Constants
|
||||||
|
|
||||||
|
```go
|
||||||
|
const Phi = 1.618
|
||||||
|
```
|
||||||
|
|
||||||
|
Constants can be character, string, boolean, or numeric values.
|
||||||
|
|
||||||
|
See: [Constants](https://tour.golang.org/basics/15)
|
||||||
|
|
||||||
|
## Basic types
|
||||||
|
{: .-three-column}
|
||||||
|
|
||||||
|
### Strings
|
||||||
|
|
||||||
|
```go
|
||||||
|
str := "Hello"
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
str := `Multiline
|
||||||
|
string`
|
||||||
|
```
|
||||||
|
|
||||||
|
Strings are of type `string`.
|
||||||
|
|
||||||
|
### Numbers
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Typical types:
|
||||||
|
num := 3 // int
|
||||||
|
num := 3. // float64
|
||||||
|
num := 3 + 4i // complex128
|
||||||
|
num :+ byte('a') // byte (alias for uint8)
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Other types:
|
||||||
|
var u uint = 7 // uint (unsigned)
|
||||||
|
var p float32 = 22.7 // 32-bit float
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arrays
|
||||||
|
|
||||||
|
```go
|
||||||
|
// var numbers [5]int
|
||||||
|
numbers := [...]int{0, 0, 0, 0, 0}
|
||||||
|
```
|
||||||
|
|
||||||
|
Arrays have a fixed size.
|
||||||
|
|
||||||
|
### Slices
|
||||||
|
|
||||||
|
```go
|
||||||
|
slice := []int{2, 3, 4}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
slice := []byte("Hello")
|
||||||
|
```
|
||||||
|
|
||||||
|
Slices have a dynamic size, unlike arrays.
|
||||||
|
|
||||||
|
### Pointers
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main () {
|
||||||
|
b := *getPointer()
|
||||||
|
fmt.Println("Value is", b)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="2"}
|
||||||
|
|
||||||
|
```go
|
||||||
|
func getPointer () (myPointer *int) {
|
||||||
|
a := 234
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="3"}
|
||||||
|
|
||||||
|
Pointers point to a memory location of a variable. Go is fully garbage-collected.
|
||||||
|
|
||||||
|
See: [Pointers](https://tour.golang.org/moretypes/1)
|
||||||
|
|
||||||
|
### Type conversions
|
||||||
|
|
||||||
|
```go
|
||||||
|
i := 2
|
||||||
|
f := float64(i)
|
||||||
|
u := uint(i)
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Type conversions](https://tour.golang.org/basics/13)
|
||||||
|
|
||||||
|
## Flow control
|
||||||
|
{: .-three-column}
|
||||||
|
|
||||||
|
### Conditional
|
||||||
|
|
||||||
|
```go
|
||||||
|
if day == "sunday" || day == "saturday" {
|
||||||
|
rest()
|
||||||
|
} else if day == "monday" && isTired() {
|
||||||
|
groan()
|
||||||
|
} else {
|
||||||
|
work()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="1,3,5"}
|
||||||
|
|
||||||
|
See: [If](https://tour.golang.org/flowcontrol/5)
|
||||||
|
|
||||||
|
### Statements in if
|
||||||
|
|
||||||
|
```go
|
||||||
|
if _, err := getResult(); err != nil {
|
||||||
|
fmt.Println("Uh oh")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="1"}
|
||||||
|
|
||||||
|
A condition in an `if` statement can be preceeded with a statement before a `;`.
|
||||||
|
|
||||||
|
See: [If with a short statement](https://tour.golang.org/flowcontrol/6)
|
||||||
|
|
||||||
|
### Switch
|
||||||
|
|
||||||
|
```go
|
||||||
|
switch day {
|
||||||
|
case "sunday":
|
||||||
|
// cases don't "fall through" by default!
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
case "saturday":
|
||||||
|
rest()
|
||||||
|
|
||||||
|
default:
|
||||||
|
work()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Switch](https://github.com/golang/go/wiki/Switch)
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
{: .-three-column}
|
||||||
|
|
||||||
|
### Lambdas
|
||||||
|
|
||||||
|
```go
|
||||||
|
myfunc := func() bool {
|
||||||
|
return x > 10000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="1"}
|
||||||
|
|
||||||
|
Functions are first class objects.
|
||||||
|
|
||||||
|
### Multiple return types
|
||||||
|
|
||||||
|
```go
|
||||||
|
a, b := getMessage()
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
func getMessage() (a string, b string) {
|
||||||
|
return "Hello", "World"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="2"}
|
||||||
|
|
||||||
|
|
||||||
|
### Named return values
|
||||||
|
|
||||||
|
```go
|
||||||
|
func split(sum int) (x, y int) {
|
||||||
|
x := sum * 4 / 9
|
||||||
|
y := sum - x
|
||||||
|
return
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="4"}
|
||||||
|
|
||||||
|
By defining the return value names in the signature, a `return` (no args) will return variables with those names.
|
||||||
|
|
||||||
|
See: [Named return values](https://tour.golang.org/basics/7)
|
||||||
|
|
||||||
|
## Concurrency
|
||||||
|
{: .-three-column}
|
||||||
|
|
||||||
|
### Goroutines
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
// A "channel"
|
||||||
|
ch := make(chan string)
|
||||||
|
|
||||||
|
// Start concurrent routines
|
||||||
|
go push("Moe", ch)
|
||||||
|
go push("Larry", ch)
|
||||||
|
go push("Curly", ch)
|
||||||
|
|
||||||
|
// Read 3 results
|
||||||
|
// (Since our goroutines are concurrent,
|
||||||
|
// the order isn't guaranteed!)
|
||||||
|
fmt.Println(<-ch, <-ch, <-ch)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="3,6,7,8,13"}
|
||||||
|
|
||||||
|
```go
|
||||||
|
func push(name string, ch chan string) {
|
||||||
|
msg := "Hey, " + name
|
||||||
|
ch <- msg
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="3"}
|
||||||
|
|
||||||
|
Channels are concurrency-safe communication objects, used in goroutines.
|
||||||
|
|
||||||
|
See: [Goroutines](https://tour.golang.org/concurrency/1), [Channels](https://tour.golang.org/concurrency/2)
|
||||||
|
|
||||||
|
### Buffered channels
|
||||||
|
|
||||||
|
```go
|
||||||
|
ch := make(chan int, 2)
|
||||||
|
ch <- 1
|
||||||
|
ch <- 2
|
||||||
|
ch <- 3
|
||||||
|
// fatal error:
|
||||||
|
// all goroutines are asleep - deadlock!
|
||||||
|
```
|
||||||
|
{: data-line="1"}
|
||||||
|
|
||||||
|
Buffered channels limit the amount of messages it can keep.
|
||||||
|
|
||||||
|
See: [Buffered channels](https://tour.golang.org/concurrency/3)
|
||||||
|
|
||||||
|
### Closing channels
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Closes a channel
|
||||||
|
ch <- 1
|
||||||
|
ch <- 2
|
||||||
|
ch <- 3
|
||||||
|
close(ch)
|
||||||
|
```
|
||||||
|
{: data-line="5"}
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Iterates across a channel until its closed
|
||||||
|
for i := range ch {
|
||||||
|
···
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Closed if ok == false
|
||||||
|
v, ok := <- ch
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Range and close](https://tour.golang.org/concurrency/4)
|
||||||
|
|
||||||
|
## Error control
|
||||||
|
|
||||||
|
### Defer
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
defer fmt.Println("Done")
|
||||||
|
fmt.Println("Working...")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="2"}
|
||||||
|
|
||||||
|
Defers running a function until the surrounding function returns.
|
||||||
|
The arguments are evaluated immediately, but the function call is not ran until later.
|
||||||
|
|
||||||
|
See: [Defer, panic and recover](https://blog.golang.org/defer-panic-and-recover)
|
||||||
|
|
||||||
|
### Deferring functions
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
defer func() {
|
||||||
|
fmt.Println("Done")
|
||||||
|
}
|
||||||
|
fmt.Println("Working...")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="2,3,4"}
|
||||||
|
|
||||||
|
Lambdas are better suited for defer blocks.
|
||||||
|
|
||||||
|
## Structs
|
||||||
|
{: .-three-column}
|
||||||
|
|
||||||
|
### Defining
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Vertex struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
}
|
||||||
|
```
|
||||||
|
{: data-line="1,2,3,4"}
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
v := Vertex{1, 2}
|
||||||
|
v.X = 4
|
||||||
|
fmt.Println(v.X, v.Y)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Structs](https://tour.golang.org/moretypes/2)
|
||||||
|
|
||||||
|
### Literals
|
||||||
|
|
||||||
|
```go
|
||||||
|
v := Vertex{X: 1, Y: 2}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Field names can be omitted
|
||||||
|
v := Vertex{1, 2}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Y is implicit
|
||||||
|
v := Vertex{X: 1}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also put field names.
|
||||||
|
|
||||||
|
### Pointers to structs
|
||||||
|
|
||||||
|
```go
|
||||||
|
v := &Vertex{1, 2}
|
||||||
|
v.X = 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Doing `v.X` is the same as doing `(*v).X`, when `v` is a pointer.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [A tour of Go](https://tour.golang.org/welcome/1) _(tour.golang.org)_
|
||||||
|
- [Golang wiki](https://github.com/golang/go/wiki/) _(github.com)_
|
Loading…
Reference in New Issue