Golang学习总结

基础语法

Channel+WaitGroup

  1. 实现发布/订阅Server:for+select循环监听发布事件、订阅事件、取消事件
  2. 工作调度器:

interface

  1. go 没有显式的关键字用来实现 interface,如果一个类型实现了一个 interface 中所有方法,我们说类型实现了该 interface

  2. go 允许不带任何方法的 interface ,这种类型的 interface 叫 empty interfacego 不会对类型是interface{} 的 slice 进行转换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 报错:cannot use names (type []string) as type []interface {} in argument to printAll
    // 原因:interface{} 会占用两个字长的存储空间,一个是自身的 methods 数据,一个是指向其存储值的指针,也就是 interface 变量存储的值;slice []interface{} 其长度是固定的N*2,但是 []T 的长度是N*sizeof(T),两种 slice 实际存储值的大小是有区别的
    func printAll(vals []interface{}) {
    for _, val := range vals {
    fmt.Println(val)
    }
    }
    func main(){
    names := []string{"stanley", "david", "oscar"}
    printAll(names)
    }

    // 手动转换成[]interface{}
    var dataSlice []int = foo()
    var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
    for i, d := range dataSlice {
    interfaceSlice[i] = d
    }
  3. interface 变量存储的是实现者的值,也就是可以申明一个interface,然后把具体的struct赋值给其进行初始化。

  4. Type assertions (类型断言),用于区分 interface 的变量究竟存储哪种类型的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    s := S{}
    var i I //声明 i
    i = &s //赋值 s 到 i

    // 方案一
    if t, ok := i.(*S); ok {
    fmt.Println("s implements I", t)
    }

    // 方案二
    switch t := i.(type) {
    case *S:
    fmt.Println("i store *S", t)
    case *R:
    fmt.Println("i store *R", t)
    }
  5. interface 定义时并没有严格规定实现者的方法 receiver 是个 value receiver 还是 pointer receiver。interface 的实现者 ss的方法 receiver 都是 value receiver,执行函数func(i)可以无论是 pointer 还是 value 都可以正确执行,也就是func(&ss)或者func(ss);如果ss的方法receiver存在pointer receiver,则不能调用func(ss),因为根据value找不到地址

  6. go 中函数都是按值传递即 passed by value。对于 receiver 是 value 的 method,任何在 method 内部对 value 做出的改变都不影响调用者看到的 value,这就是按值传递。

参考链接

  1. 理解 Go interface 的 5 个关键点

其它

gofmt与goimports

gofmt follows a simple rule that works for all use cases: imports may be separated by
blank lines, and each set of blank lines is sorted independently.

goimports, which does more than just formatting, applies a different rule: it groups
imports according to whether they are standard imports, appengine imports, or other
imports. It emits each group separately. Then the gofmt algorithm kicks in and sorts
each group independently.
The goimports and gofmt programs do different jobs and it is not a goal that they
produce identical results.