GO

字数 1941 · 2020-03-25

Features

  • GC
  • Concurrency
  • powerful STD Lib
  • Binary
  • Cross platform

Hello World

1
2
3
4
5
6
7
8
// The entry point for the application is the main function in the main package
package main

import "fmt"

func main() {
	fmt.Printf("hello, world\n")
}
1
2
go build hello.go
./hello

https://go.dev/ref/spec#Program_execution

CLI

  • env
  • work

ENV

1
export GOPATH=$HOME/go

GOOS and GOARCH for cross-platform compiling

Package

Exported names

In Go, a name is exported if it begins with a capital letter. For example, Pizza is an exported name, as is Pi, which is exported from the math package.

pizza and pi do not start with a capital letter, so they are not exported.

Init

Module

1
go mod tidy

Functions

1
2
3
func add(x int, y int) int {
	return x + y
}

Multiple Return Values

1
2
3
4
5
func f1() (int, int) {
    return 3, 7
}

a, b := f1()

Variables

The var statement declares a list of variables; as in function argument lists, the type is last.

1
2
3
var c, python, java bool

var i, j int = 1, 2

Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type.

Outside a function, every statement begins with a keyword (var, func, and so on) and so the := construct is not available.

Basic types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // alias for uint8

rune // alias for int32
     // represents a Unicode code point

float32 float64

complex64 complex128

Constants

1
const World = "World"

iota

Loop

Go has only one looping construct, the for loop.

The basic for loop has three components separated by semicolons:

  • the init statement: executed before the first iteration
  • the condition expression: evaluated before every iteration
  • the post statement: executed at the end of every iteration
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum)
}

If

1
2
3
4
5
if v := math.Pow(x, n); v < lim {
	return v
} else {
	return 1
}

Note that you don’t need parentheses around conditions in Go, but the braces are required.

Switch

A switch statement is a shorter way to write a sequence of if - else statements.

Go’s switch is like the one in C, C++, Java, JavaScript, and PHP, except that Go only runs the selected case, not all the cases that follow.

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
    i := 2
    fmt.Print("Write ", i, " as ")
    switch i {
    case 1:
        fmt.Println("one")
    case 2:
        fmt.Println("two")
    case 3:
        fmt.Println("three")
    }
}

Defer

A defer statement defers the execution of a function until the surrounding function returns.

Deferred function calls are pushed onto a stack.

Pointer

Struct

Pointer to structs

To access the field X of a struct when we have the struct pointer p we could write (*p).X. However, that notation is cumbersome, so the language permits us instead to write just p.X, without the explicit dereference.

1
2
3
4
5
6
var (
	v1 = Vertex{1, 2}  // has type Vertex
	v2 = Vertex{X: 1}  // Y:0 is implicit
	v3 = Vertex{}      // X:0 and Y:0
	p  = &Vertex{1, 2} // has type *Vertex
)

Array

1
2
3
q := []int{2, 3, 5, 7, 11, 13}

arr := [5]string{1:"b", 3:"d"}

The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.

The zero value of a slice is nil.

Slice

1
2
3
s := make([]string, 3)

q := []int{2, 3, 5, 7, 11, 13}

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var m map[string]Vertex

func main() {
	m = make(map[string]Vertex)
	m["Bell Labs"] = Vertex{
		40.68433, -74.39967,
	}
	fmt.Println(m["Bell Labs"])

	// check if exist
	value,ok := m["Be"]
	if ok {
		fmt.Println(value)
	}
}

Map literals

1
2
3
4
5
6
7
8
var m = map[string]Vertex{
	"Bell Labs": Vertex{
		40.68433, -74.39967,
	},
	"Google": Vertex{
		37.42202, -122.08408,
	},
}

Delete an element:

1
delete(m, key)

Test that a key is present with a two-value assignment:

If key is in m, ok is true. If not, ok is false.

1
2
	v, ok := m["Answer"]
	fmt.Println("The value:", v, "Present?", ok)

Method

Go does not have classes. However, you can define methods on types.

A method is a function with a special receiver argument.

The receiver appears in its own argument list between the func keyword and the method name.

1
2
3
4
5
6
7
8
9
10
11
12
13
type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}

Remember: a method is just a function with a receiver argument.

You can declare a method on non-struct types, too.

Interface

1
2
3
type Abser interface {
	Abs() float64
}

There is no explicit declaration of intent, no "implements" keyword.

1
t := i.(T)

This statement asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t.

Type Switch

1
2
3
4
5
6
7
8
switch v := i.(type) {
case T:
    // here v has type T
case S:
    // here v has type S
default:
    // no match; here v has the same type as i
}

The declaration in a type switch has the same syntax as a type assertion i.(T), but the specific type T is replaced with the keyword type.

One of the most ubiquitous interfaces is Stringer defined by the fmt package.

1
2
3
type Stringer interface {
    String() string
}

Error

Panic

Reflect

Test

Unit Test

1
go test test_dir

Coverage

Benchmark

Lint

golangci-lint

Gin

RPC

Tips

Go 语言中,参数的传递为值传递

map, chan 均为指针类型

make 函数用于 slice, map, chan 的初始化

slice 自动扩容时,会创建一个新数组,再把原来的元素拷贝过去。