Gocheatsheet
贡献者:BAI
GO
介绍
Hello world
hello.go
GOpackage mainimport "fmt"func main() { message := greetMe("world") fmt.Println(message)}func greetMe(name string) string { return "Hello, " + name + "!"}
BASHgo build
也可以在 Go repl,或 A Tour of Go. 做实验
变量
变量声明
GOvar msg stringmsg = "Hello"
缩写(推断类型)
GOmsg := "Hello"
常量
GOconst Phi = 1.618
常量可以是字符、字符串、布尔值或数字类型
详见: Constants
基本类型
字符串
GOstr := "Hello"
GOstr := `Multilinestring`
数字
基本的数字类型
GOnum := 3 // intnum := 3. // float64num := 3 + 4i // complex128num := byte('a') // byte (alias for uint8)
其他类型
GOvar u uint = 7 // uint (无符号)var p float32 = 22.7 // 32-bit float
数组
GO// var numbers [5]intnumbers := [...]int{0, 0, 0, 0, 0}
数组需要一个固定的尺寸
Slice
GOslice := []int{2, 3, 4}
GOslice := []byte("Hello")
Slice 类型可以有动态的尺寸
指针
GOfunc main () { b := *getPointer() fmt.Println("Value is", b)}
GOfunc getPointer () (myPointer *int) { a := 234 return &a}
GOa := new(int)*a = 234
指针指向一个变量的内存所在的位置,Go 是一种完全的垃圾回收机制的语言。 Pointers point to a memory location of a variable. Go is fully garbage-collected.
详见: 指针
类型转换
GOi := 2f := float64(i)u := uint(i)
详见: 类型转换
控制流
条件语句
GOif day == "sunday" || day == "saturday" { rest()} else if day == "monday" && isTired() { groan()} else { work()}
详 f: If
if 条件中的语句
GOif _, err := doThing(); err != nil { fmt.Println("Uh oh")}
在 if
语句中可以执行一系列其他带 ;
的语句。生命的变量仅在 if
这个作用域内生效
Switch 语句
GOswitch day { case "sunday": // case 语句不会向下vixy fallthrough case "saturday": rest() default: work()}
详见: Switch
For 循环
GOfor count := 0; count <= 10; count++ { fmt.Println("My counter is at", count)}
详见: For 循环
For-Range 循环
GOentry := []string{"Jack","John","Jones"}for i, val := range entry { fmt.Printf("At position %d, the character %s is present\n", i, val)}
详见: For-Range 循环
While 循环
GOn := 0x := 42for n != x { n := guess()}
详见: Go 的 "while"
函数
Lambda
GOmyfunc := func() bool { return x > 10000}
函数是第一个类对象
多类型返回
GOa, b := getMessage()
GOfunc getMessage() (a string, b string) { return "Hello", "World"}
带命名的返回值
GOfunc split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return}
包
导入
GOimport "fmt"import "math/rand"
GOimport ( "fmt" // gives fmt.Println "math/rand" // gives rand.Intn)
上面两者等效
详见: Importing
别名
GOimport r "math/rand"
GOr.Intn()
导出命名
GOfunc Hello () { ···}
导出的名称需要大写开头
详见: Exported names
包
GOpackage hello
Every package file has to start with package
.
并发
Goroutines
GOfunc main() { // 一个 Channel ch := make(chan string) // 开始并发 go push("Moe", ch) go push("Larry", ch) go push("Curly", ch) // 读取 3 个结果 // 因为goroutines 是并发的,所以顺序不固定 fmt.Println(<-ch, <-ch, <-ch)}
GOfunc push(name string, ch chan string) { msg := "Hey, " + name ch <- msg}
Channel 是并发安全的通讯对象,可以在 goroutines 中 使用
详见: Goroutines, Channels
带缓存的 Channel
GOch := make(chan int, 2)ch <- 1ch <- 2ch <- 3// fatal error:// all goroutines are asleep - deadlock!
带缓存的 Channel 限制了可以保存的消息的数量
关闭 Channel
关闭一个 Channel
GOch <- 1ch <- 2ch <- 3close(ch)
迭代 Channel 直到频道关闭
GOfor i := range ch { ···}
如果 ok === false
则关闭
GOv, ok := <- ch
详见: Range and close
WaitGroup
GOimport "sync"func main() { var wg sync.WaitGroup for _, item := range itemList { // 增加 WaitGroup 计数器 wg.Add(1) go doOperation(item) } // 等待 goroutines 完成 wg.Wait()}
GOfunc doOperation(item string) { defer wg.Done() // do operation on item // ...}
一个 WaitGroup 会等待一组 goroutines 执行完毕。主 goroutines 执行时会添加其他需要等待的 goroutines。 goroutines 执行 wg.Done()
时结束
详见: WaitGroup
错误控制
Defer
GOfunc main() { defer fmt.Println("Done") fmt.Println("Working...")}
Defer 可以执行一个函数,直到被包裹的函数返回,其参数会直接计算,但函数调用不会直接执行
Defer 函数
GOfunc main() { defer func() { fmt.Println("Done") }() fmt.Println("Working...")}
Lambda 操作符更适合 defer 块
GOfunc main() { var d = int64(0) defer func(d *int64) { fmt.Printf("& %v Unix Sec\n", *d) }(&d) fmt.Print("Done ") d = time.Now().Unix()}
除非我们用一个指针去在在 main 函数的末尾去取值,不然 Defer 函数会使用当前 d 的值,
结构体
定义
GOtype Vertex struct { X int Y int}
GOfunc main() { v := Vertex{1, 2} v.X = 4 fmt.Println(v.X, v.Y)}
详见: Structs
语法
GOv := Vertex{X: 1, Y: 2}
GO// 字段名可省略v := Vertex{1, 2}
GO// Y 是隐式的v := Vertex{X: 1}
你也可以设置字段名
结构体指针
GOv := &Vertex{1, 2}v.X = 2
当 v
是指针时。v.X
和 (*v).X
一样;
方法
Receiver
GOtype Vertex struct { X, Y float64}
GOfunc (v Vertex) Abs() float64 { return math.Sqrt(v.X * v.X + v.Y * v.Y)}
GOv := Vertex{1, 2}v.Abs()
上面这些不是类,但是你可以用 receivers 定义方法
详见: Methods
Mutation
GOfunc (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f}
GOv := Vertex{6, 12}v.Scale(0.5)// `v` is updated
通过将你的 receiver 定义为一个指针,你可以直接修改其中的值。
接口
基本接口
GOtype Shape interface { Area() float64 Perimeter() float64}
结构
GOtype Rectangle struct { Length, Width float64}
Rectangle
结构通过实现了 Shape
的全部方法隐式实现了 Shape
接口
方法
GOfunc (r Rectangle) Area() float64 { return r.Length * r.Width}func (r Rectangle) Perimeter() float64 { return 2 * (r.Length + r.Width)}
这些方法定义在 Shape
中,并在 Rectangle
中实现。
接口示例
GOfunc main() { var r Shape = Rectangle{Length: 3, Width: 4} fmt.Printf("Type of r: %T, Area: %v, Perimeter: %v.", r, r.Area(), r.Perimeter())}
参考
官方资料
- A tour of Go (tour.golang.org)
- Golang wiki (github.com)
- Effective Go (golang.org)
其他链接
- Go by Example (gobyexample.com)
- Awesome Go (awesome-go.com)
- JustForFunc Youtube (youtube.com)
- Style Guide (github.com)