Baisc 基础
Hello world
hello.go
package main
import "fmt"
func main() {
message := greetMe("world")
fmt.Println(message)
}
func greetMe(name string) string {
return "Hello, " + name + "!"
}
cli
$ go build
Variables 变量
Variable declaration
var msg string
msg = "Hello"
Shortcut of above (Infers type)
msg := "Hello"
Constants 常量
const Phi = 1.618
Constants can be character, string, boolean, or numeric values.
Basic types 基础类型
Strings 字符串
str := "Hello"
str := `Multiline
string`
Strings are of type string.
Numbers 数字类型
Typical types
num := 3 // int 整数
num := 3. // float64 浮点
num := 3 + 4i // complex128 复数
num := byte('a') // byte (alias for uint8) 字节类型
Other types
var u uint = 7 // uint (unsigned)
var p float32 = 22.7 // 32-bit float
Arrays 数组
// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}
Arrays have a fixed size.
数组类型是固定长度, 不同长度的数组是不同的类型的数组。
Slices 切片
slice := []int{2, 3, 4}
slice := []byte("Hello")
切片数组是动态长度。 Slices have a dynamic size, unlike arrays.
Pointers
func main () {
b := *getPointer()
fmt.Println("Value is", b)
}
func getPointer () (myPointer *int) {
a := 234
return &a
}
Pointers point to a memory location of a variable. Go is fully garbage-collected.
See: Pointers
Type conversions
i := 2
f := float64(i)
u := uint(i)
See: Type conversions
Flow control
Conditional
if day == "sunday" || day == "saturday" {
rest()
} else if day == "monday" && isTired() {
groan()
} else {
work()
}
See: If
Statements in if
if _, err := getResult(); err != nil {
fmt.Println("Uh oh")
}
A condition in an if statement can be preceded with a statement before a ;.
See: If with a short statement
Switch
switch day {
case "sunday":
// cases don't "fall through" by default!
fallthrough
case "saturday":
rest()
default:
work()
}
See: Switch
For loop
for count := 0; count <= 10; count++ {
fmt.Println("My counter is at", count)
}
See: For loops
range 历谝
For-Range loop
entry := []string{"Jack","John","Jones"}
for i, val := range entry {
fmt.Printf("At position %d, the character %s is present\n", i, val)
}
See: For-Range loops
函数 Functions
闭包函数 Lambdas
myfunc := func() bool {
return x > 10000
}
Functions are first class objects.
多个返回
Multiple return types
a, b := getMessage()
func getMessage() (a string, b string) {
return "Hello", "World"
}
命名返回
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
使用命名返回数据,在使用 return
不用使用标记,自动返回命名对象。
Packages
Importing
import "fmt"
import "math/rand"
import (
"fmt" // gives fmt.Println
"math/rand" // gives rand.Intn
)
Both are the same.
See: Importing
Aliases
import r "math/rand"
r.Intn()
Exporting names
func Hello () {
···
}
Exported names begin with capital letters.
See: Exported names
Packages
package hello
Every package file has to start with package.
Concurrency
Goroutines
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)
}
func push(name string, ch chan string) {
msg := "Hey, " + name
ch <- msg
}
Channels are concurrency-safe communication objects, used in goroutines.
See: Goroutines, Channels
Buffered channels
ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// fatal error:
// all goroutines are asleep - deadlock!
Buffered channels limit the amount of messages it can keep.
See: Buffered channels
Closing channels
Closes a channel
ch <- 1
ch <- 2
ch <- 3
close(ch)
Iterates across a channel until its closed
for i := range ch {
···
}
Closed if ok == false
v, ok := <- ch
See: Range and close
Error control
Defer
func main() {
defer fmt.Println("Done")
fmt.Println("Working...")
}
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
Deferring functions
func main() {
defer func() {
fmt.Println("Done")
}()
fmt.Println("Working...")
}
Lambdas are better suited for defer blocks.
Structs
Defining
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X, v.Y)
}
See: Structs
Literals
v := Vertex{X: 1, Y: 2}
// Field names can be omitted
v := Vertex{1, 2}
// Y is implicit
v := Vertex{X: 1}
You can also put field names.
Pointers to structs
v := &Vertex{1, 2}
v.X = 2
Doing v.X
is the same as doing (*v).X
, when v is a pointer.
Methods
Receivers
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
v: = Vertex{1, 2}
v.Abs()
There are no classes, but you can define functions with receivers.
See: Methods
Mutation
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
v := Vertex{6, 12}
v.Scale(0.5)
// `v` is updated
By defining your receiver as a pointer (*Vertex), you can do mutations.
See: Pointer receivers