More: More Dengqinghua

Go 学习

2018-06-05

该部分包含了Go的学习计划和相关知识树

阅读完该文档后,您将会了解到:

1 提问的智慧

如何提问很重要, 在学习任何知识之前, 需要先学会正确地提问.

  • 提问的智慧原文: 这里
  • 提问的智慧中文版本: 这里

2 Go Proverbs

Simple, Poetic, Pithy

Go Proverbs - Rob Pike - Gopherfest

  • Don't communicate by sharing memory, share memory by communicating.
  • Concurrency is not parallelism.
  • Channels orchestrate; mutexes serialize.
  • The bigger the interface, the weaker the abstraction.
  • Make the zero value useful.
  • interface{} says nothing.
  • Gofmt's style is no one's favorite, yet gofmt is everyone's favorite. WHO CARES? SHUT UP
  • A little copying is better than a little dependency.
  • Syscall must always be guarded with build tags.
  • Cgo must always be guarded with build tags.
  • Cgo is not Go.
  • With the unsafe package there are no guarantees.
  • Clear is better than clever.
  • Reflection is never clear.
  • Errors are values.
  • Don't just check errors, handle them gracefully.
  • Design the architecture, name the components, document the details.
  • Documentation is for users.
  • Don't panic.

3 5 things of Go's success

As the saying goes... history doesn’t repeat itself, but it often rhymes.

  • Formal specification
  • Attracted killer apps (Docker, k8s)
  • the Open source community
  • Made the language hard to change
  • Stuck with features they believed in

5-things-rob-pike-attributes-to-gos-success

4 Vim-Go

Vim and ONLY Vim.

plugin 'fatih/vim-go'
:GoInstallBinaries
:help vim-go

如果执行 :GoInstallBinaries 报错, 请参考 go_get_timeout_solution

5 Go Style

规范, 约定大于配置, 好的习惯比什么都重要.

6 Test

TDD

最终选择的是 Goconvey

测试Case如下:

package golang

import (
    . "github.com/smartystreets/goconvey/convey"
    "testing"
)

// go test -v -run TestBasicMap
func TestBasicMap(t *testing.T) {
    Convey("TestBasicMap", t, func() {
        Convey("get, put", func() {
            Convey("should get right", func() {
                oneMap := make(map[string]int)

                oneMap["dsgv"] = 587

                value, exist := oneMap["dsgv"]

                So(exist, ShouldBeTrue)
                So(value, ShouldEqual, 587)

                value, exist = oneMap["dsg"]

                So(exist, ShouldBeFalse)
                So(value, ShouldEqual, 0)
            })
        })
    })
}

6.1 Test Func

测试单独的一个方法

hello_world.go

package main

// go run hello_world.go
// go build hello_world.go
// :GoRun / :GoBuild
func main() {
    println(Sum(5, 5))
}

func Sum(x int, y int) int {
    return x + y
}

hello_world_test.go

package main

import "testing"

// go test -run TestSum
func TestSum(t *testing.T) {
    total := Sum(5, 5)

    if total != 5 {
        // t.Errorf; t.Fail; t.Log
        t.Errorf("Sumw was incorrect, got %d, want %d", total, 10)
    }
}

// go test -run TestSum1
func TestSum1(t *testing.T) {
    total := Sum(5, 5)

    if total != 6 {
        // t.Errorf; t.Fail; t.Log
        t.Errorf("Sumw was incorrect, got %d, want %d", total, 10)
    }
}

测试全部的case

go test

测试某个case

go test -run TestSum

test文件必须写成 *_test 的形式. 可以执行 go help test 查看更多信息.

6.2 Mock

学会mock方法. 考察了很多 mock 的插件, 如 testify/mock, Gomock, Gostub 等, 最终我们选择了 testify/mock

Golang 的 mock, 不像面向对象语言, 她只能对 interface 进行mock. 有人对此也提出了疑问, 详情请见 How to write mock for structs in Go

代码请见我的mock_test

7 Debugger

学会调试, 查看源码, 阅读源码.

由于 Vim Godebug 依赖 Neovim, 而我们一般使用的是vim, 故最终选择的调试工具为 sebdah/vim-delve, vim-delve 依赖 Shougo/vimshell.vim.

delve-demo

8 基础知识

package main
import "fmt"

var a = 1

func main() {
  fmt.Println("Hello World")
}

8.1 Spec部分笔记

8.1.1 Predeclared Identifiers and Keywords

Predeclared Identifiers 是可以被使用的

Types:
    bool byte complex64 complex128 error float32 float64
    int int8 int16 int32 int64 rune string
    uint uint8 uint16 uint32 uint64 uintptr

Constants:
    true false iota

Zero value:
    nil

Functions:
    append cap close complex copy delete imag len
    make new panic print println real recover

如下面的语法是Okay的

bool := 1
fmt.Println(bool)

Keywords 是不可以被重复使用的, 包括下面这些

break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

8.1.2 Slice

A slice is

  • a data structure describing a contiguous section of an array stored separately from the slice variable itself
  • a data structure with two elements: a length and a pointer to an element of an array
type sliceHeader struct {
    Length        int
    Capacity      int
    ZerothElement *byte
}

A slice cannot be grown beyond its capacity. Attempting to do so will cause a runtime panic. Similarly, slices cannot be re­sliced below zero to access earlier elements in the array.

8.1.3 Rune

A rune literal represents a rune constant, an integer value identifying a Unicode code point, or think of as a character constant is called a rune constant in Go.

Strings, bytes, runes and characters in Go

  • A string is in effect a read-only slice of bytes

ASCII, UNICODE 和 UTF-8

8.2 GoPath

Code organization

go help

8.3 Go Tags in structures

9 并发

9.1 sync Package

10 其他

11 项目

11.1 Go Strings

用Go语言做跟音乐相关的东西, 正在筹划中

12 Books