golang base (three)

error 处理

  • 没有异常机制
  • error 类型实现了 error 接口

    1
    2
    3
    type error interface{
    Error string
    }
  • 可以通过 errors.New 来快速创建错误实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    errors.New(" error info")
    var NumberLess2Error = errors.New("n must be not less than 2")
    var NumberLarger100Error = errors.New("n must be not larger than 100")
    func GetFibonacci(n int) (c []int, err error) {
    // 及早失败
    if n < 2 {
    err = NumberLess2Error
    return
    }
    if n > 100 {
    err = NumberLarger100Error
    return
    }
    c = append(c, 1,1)
    a, b := 1, 1
    for i := 0; i < n; i++ {
    a, b = b, a+b
    c = append(c, b)
    }
    return c, nil
    }

    func TestGetFibonacci(t *testing.T) {
    if n,err := GetFibonacci(-10);err!=nil{
    if err == NumberLess2Error{
    fmt.Printf("less ")
    }
    t.Error(err)
    }else {
    t.Log(n)
    }
    }

panicrecover

  • panicos.Exit

    • os.Exit 退出时不会调用 defer 指定的函数
    • os.Exit 退出时不输出当前调用栈信息
  • recover 错误恢复,类似于java与php 的 try{}catch(){}

    1
    2
    3
    4
    5
    6
    7
    8
    9
     func TestPanicVxExit(t *testing.T) {
    defer func() {
    if err := recover(); err != nil {
    fmt.Println("recover from:", err)
    }
    }()
    fmt.Println("Start")
    panic(errors.New("Something is Wrong"))
    }
  • recover 成为恶魔

    • 形成僵尸服务进程,导致 health check 失效
    • “Let it Crash!” 往往是我们恢复不确定性的最好方法 简称实在不行就重启

package 构建可复用的模块

  • 基本复用单元
    • 以首字母大写来表明可被包外当代码访问
  • 代码的package 可以和所在目录不一致
  • 同一目录里的 Go 代码的 package 要保持一致
  • init 方法
    • 在main被执行前,所有依赖的 package 的init 方法 都会被执行
    • 不同包的init 函数按照包的依赖关系决定执行顺序
    • 每个包可以有多个init 函数
    • 包的每个源文件也可以有多个 init 函数,这点很特殊
  • 通过go get 来获取远程依赖
    • go get -u 每次都去拉取最新的包
    • 包是从GOPATH/src/ 开始算的
  • 注意代码在Github 上的组织形式,以适应 go get
    • 直接以代码路径开始,不要有src

依赖管理

  • Go未解决的依赖问题
    • 同一环境下,不同项目使用同一包的不同版本
    • 无法管理对包的特定版本的依赖
  • vendor 路径
    • 随着 Go 1.5 版本的发布,vendor目录被添加到除了GOPATH 与 GOROOT 之外的依赖目录查找方案,在go 1.6以前,需要手动的设置环境变量
  • 查找依赖包路径的解决方案如下
      1. 在当前包下的 vendor 目录
      1. 向上级目录查找,直到找到src下的 vendor 目录
      1. 在 GOPATH 下面查找
      1. 在 GOROOT 下面查找
  • 第三方依赖管理工具

协程机制

  • 线程与携程 Thead vs Groutine
    • JDK5 以后 java thread stack 默认为 1M
    • Groutine 的 Stack 初始化大小为 2K
  • 和 KSE(Kernel Speace Entity)的对应关系
    • java thread 是 1:1
    • Groutine 是 M:N 多对多
    • 系统线程切换的消耗 比较大 go与系统线程是多对多关系,无需系统的线程切换,自己去调度,尽可能的去利用系统线程的能力