我本身有啥语言都会点,所以这门语言我会用其他语言的特性来描述,请谨慎阅读

基本抄自https://gfw.go101.org/ 值得一看

golang槽点太多。写出坑来都毫无感觉

[toc]

研究一个语言要关注哪些地方?

  • 使用(生态,命令行,包管理/代理等)
  • 语言特性(核心卖点,人无我有的)
  • 类型系统( 值类型还是引用类型?)
  • 优化点 profile 内存分配器 延迟相关/GC等等

相关命令行

下载包

go get github.com/onsi/gomega

如果离线安装,得克隆到goroot目录里面

更新mod

go mod tidy

语言功能


  • channel以及select-case

select-case分支流程控制代码块

Go中有一个专门为通道设计的 select-case分支流程控制语法。 此语法和 switch-case分支流程控制语法很相似。 比如,select-case流程控制代码块中也可以有若干 case分支和最多一个 default分支。 但是,这两种流程控制也有很多不同点。在一个 select-case流程控制中,

  • select关键字和 {之间不允许存在任何表达式和语句。
  • fallthrough语句不能被使用.
  • 每个 case关键字后必须跟随一个通道接收数据操作或者一个通道发送数据操作。 通道接收数据操作可以做为源值出现在一条简单赋值语句中。 以后,一个 case关键字后跟随的通道操作将被称为一个 case操作。
  • 所有的非阻塞 case操作中将有一个被随机选择执行(而不是按照从上到下的顺序),然后执行此操作对应的 case分支代码块。
  • 在所有的 case操作均为阻塞的情况下,如果 default分支存在,则 default分支代码块将得到执行; 否则,当前协程将被推入所有阻塞操作中相关的通道的发送数据协程队列或者接收数据协程队列中,并进入阻塞状态。

按照上述规则,一个不含任何分支的 select-case代码块 select{}将使当前协程处于永久阻塞状态。

select-case流程控制的实现机理

select-case流程控制是Go中的一个重要和独特的特性。 下面列出了官方标准运行时中 select-case流程控制的实现步骤

  1. 将所有 case操作中涉及到的通道表达式和发送值表达式按照从上到下,从左到右的顺序一一估值。 在赋值语句中做为源值的数据接收操作对应的目标值在此时刻不需要被估值。
  2. 将所有分支随机排序。default分支总是排在最后。 所有 case操作中相关的通道可能会有重复的。
  3. 为了防止在下一步中造成(和其它协程互相)死锁,对所有 case操作中相关的通道进行排序。 排序依据并不重要,官方Go标准编译器使用通道的地址顺序进行排序。 排序结果中前 N个通道不存在重复的情况。 N为所有 case操作中涉及到的不重复的通道的数量。 下面,通道锁顺序***是针对此排序结果中的前 N个通道来说的,通道锁逆序***是指此顺序的逆序。
  4. 按照上一步中的生成通道锁顺序获取所有相关的通道的锁。
  5. 按照第2步中生成的分支顺序检查相应分支:

    1. 如果这是一个 case分支并且相应的通道操作是一个向关闭了的通道发送数据操作,则按照通道锁逆序解锁所有的通道并在当前协程中产生一个恐慌。 跳到第12步。
    2. 如果这是一个 case分支并且相应的通道操作是非阻塞的,则按照通道锁逆序解锁所有的通道并执行相应的 case分支代码块。 (此相应的通道操作可能会唤醒另一个处于阻塞状态的协程。) 跳到第12步。
    3. 如果这是 default分支,则按照通道锁逆序解锁所有的通道并执行此 default分支代码块。 跳到第12步。

      (到这里,default分支肯定是不存在的,并且所有的case操作均为阻塞的。)

  6. 将当前协程(和对应 case分支信息)推入到每个 case操作中对应的通道的发送数据协程队列或接收数据协程队列中。 当前协程可能会被多次推入到同一个通道的这两个队列中,因为多个 case操作中对应的通道可能为同一个。
  7. 使当前协程进入阻塞状态并且按照通道锁逆序解锁所有的通道。
  8. …,当前协程处于阻塞状态,等待其它协程通过通道操作唤醒当前协程,…
  9. 当前协程被另一个协程中的一个通道操作唤醒。 此唤醒通道操作可能是一个通道关闭操作,也可能是一个数据发送/接收操作。 如果它是一个数据发送/接收操作,则(当前正被解释的 select-case流程中)肯定有一个相应 case操作与之配合传递数据。 在此配合过程中,当前协程将从相应 case操作相关的通道的接收/发送数据协程队列中弹出。
  10. 按照第3步中的生成的通道锁顺序获取所有相关的通道的锁。
  11. 将当前协程从各个case

    操作中对应的通道的发送数据协程队列或接收数据协程队列中(可能以非弹出的方式)移除。

    1. 如果当前协程是被一个通道关闭操作所唤醒,则跳到第5步。
    2. 如果当前协程是被一个数据发送/接收操作所唤醒,则相应的 case分支已经在第9步中知晓。 按照通道锁逆序解锁所有的通道并执行此 case分支代码块。
  12. 完毕。

从此实现中,我们得知

  • 一个协程可能同时多次处于同一个通道的发送数据协程队列或接收数据协程队列中。
  • 当一个协程被阻塞在一个 select-case流程控制中并在以后被唤醒时,它可能会从多个通道的发送数据协程队列和接收数据协程队列中被移除。

channel简单用法

通知


package main

import (
	"crypto/rand"
	"fmt"
	"os"
	"sort"
)

func main() {
	values := make([]byte, 32 * 1024 * 1024)
	if _, err := rand.Read(values); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	done := make(chan struct{}) // 也可以是缓冲的

	// 排序协程
	go func() {
		sort.Slice(values, func(i, j int) bool {
			return values[i] < values[j]
		})
		done <- struct{}{} // 通知排序已完成
	}()

	// 并发地做一些其它事情...

	<- done // 等待通知
	fmt.Println(values[0], values[len(values)-1])
}
package main

import "log"
import "time"

type T = struct{}

func worker(id int, ready <-chan T, done chan<- T) {
	<-ready // 阻塞在此,等待通知
	log.Print("Worker#", id, "开始工作")
	// 模拟一个工作负载。
	time.Sleep(time.Second * time.Duration(id+1))
	log.Print("Worker#", id, "工作完成")
	done <- T{} // 通知主协程(N-to-1)
}

func main() {
	log.SetFlags(0)

	ready, done := make(chan T), make(chan T)
	go worker(0, ready, done)
	go worker(1, ready, done)
	go worker(2, ready, done)

	// 模拟一个初始化过程
	time.Sleep(time.Second * 3 / 2)
	// 单对多通知
  close(ready)
	// 等待被多对单通知
	<-done; <-done; <-done
}

  • test的执行顺序 TestMain ->Test* 如果有TestMain, 必须有m.Run()否则本模块内部的Test*不执行
  • go的map默认是引用类型,要想复制修改,必须make
  • go的字符数组也是默认引用的
  • go不能直接赋值给PB的字段,必须构造,否则会segfault panic
  • 和nil指针比较是有类型的
assert.Equal(t, (*metadata)(nil), mymetadata, "meta nill check")
  • 没有参数的捕获默认是引用捕获,深坑,要看能否求值出。这里借用群友的一张图

这里有个解决方案https://zhuanlan.zhihu.com/p/351428978

for i := 0; i < 10; i++ {
  go func(x int) {
    fmt.Println(x)
  }(i)
}
  • time比较

我遇到的场景,是time保存到mongo在读回来,就多了location信息,不能直接比较,不相等

        	Error:      	Not equal: 
        	            	expected: time.Time{wall:0xa4fc540, ext:63761777875, loc:(*time.Location)(nil)}
        	            	actual  : time.Time{wall:0xc0338154ca582af8, ext:10214780624, loc:(*time.Location)(0x15b1ee0)}
        	        
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,5 +1,136 @@
        	            	 (time.Time) {
        	            	- wall: (uint64) 173000000,
        	            	- ext: (int64) 63761777875,
        	            	- loc: (*time.Location)(<nil>)
        	            	+ wall: (uint64) 13849555480266418936,
        	            	+ ext: (int64) 10214780624,
        	            	+ loc: (*time.Location)({
        	            	+  name: (string) (len=5) "Local",
        	            	+  zone: ([]time.zone) (len=3) {
        	            	+   (time.zone) {
        	            	+    name: (string) (len=3) "LMT",
        	            	+    offset: (int) 29143,
        	            	+    isDST: (bool) false
        	            	+   },
//以下省略一百行timezone信息,太傻逼了

查文档,用time.equal,也不好使,最终用unix来比较

assert.Equal(t, doc.CreateTime.Unix(), createtime.Unix(), "time check  error")

忙活一晚上

  • 判定结构体是否为空
package main
import (
  "fmt"
)

type Person struct {
}

func main() {
  var st Person
  if (Person{} == st) {
      fmt.Println("It is an empty structure")
  } else {
    fmt.Println("It is not an empty structure")
  }
}

如果结构体比较复杂不能直接比较,用deepEqual

package main

import (
  "fmt"
  "reflect"
)

type Person struct {
  age int
}

func (x Person) IsStructureEmpty() bool {
  return reflect.DeepEqual(x, Person{})
}

func main() {
  x := Person{}
  if x.IsStructureEmpty() {
    fmt.Println("Structure is empty")
  } else {
    fmt.Println("Structure is not empty")
  }
}

  • go testify对于结构体的比较,可能会触发内存泄漏
非常长的一段堆栈

goroutine 718 [running]: runtime.systemstack_switch() /usr/local/go/src/runtime/asm_amd64.s:330 fp=0xc000a39e08 sp=0xc000a39e00 pc=0x47afe0 runtime.mallocgc(0x5ff45b34d, 0xe1ac60, 0x1, 0x2b) /usr/local/go/src/runtime/malloc.go:1070 +0x7e6 fp=0xc000a39ea8 sp=0xc000a39e08 pc=0x410f06 runtime.makeslice(0xe1ac60, 0x5ff45b34d, 0x5ff45b34d, 0x2) /usr/local/go/src/runtime/slice.go:98 +0x6f fp=0xc000a39ee0 sp=0xc000a39ea8 pc=0x45a18f bytes.makeSlice(0x5ff45b34d, 0x0, 0x0, 0x0) /usr/local/go/src/bytes/buffer.go:229 +0x73 fp=0xc000a39f20 sp=0xc000a39ee0 pc=0x5143f3 bytes.(*Buffer).grow(0xc000726630, 0x2b, 0x0) /usr/local/go/src/bytes/buffer.go:142 +0x15c fp=0xc000a39f70 sp=0xc000a39f20 pc=0x513d3c bytes.(*Buffer).Write(0xc000726630, 0xc6fbba4d20, 0x2b, 0x2b, 0xc6fbba4d20, 0x2b, 0x2b) /usr/local/go/src/bytes/buffer.go:172 +0xe5 fp=0xc000a39fa8 sp=0xc000a39f70 pc=0x514065 github.com/davecgh/go-spew/spew.(*dumpState).indent(0xc000a40ab0) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:67 +0xc2 fp=0xc000a3a010 sp=0xc000a39fa8 pc=0xd5aca2 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4d60, 0xc0001d8640, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:416 +0x3a6 fp=0xc000a3a188 sp=0xc000a3a010 pc=0xd5c2e6 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe93400, 0xc0001d8640, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3a300 sp=0xc000a3a188 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xeb2060, 0xc0001d8640, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3a478 sp=0xc000a3a300 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpSlice(0xc000a40ab0, 0xe087c0, 0xc000198bb8, 0x1b7) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:238 +0x125 fp=0xc000a3a590 sp=0xc000a3a478 pc=0xd5b845 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe087c0, 0xc000198bb8, 0x1b7) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:352 +0x9e6 fp=0xc000a3a708 sp=0xc000a3a590 pc=0xd5c926 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4ee0, 0xc000198bb8, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3a880 sp=0xc000a3a708 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4e20, 0xc000198bb0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3a9f8 sp=0xc000a3a880 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xdf43c0, 0xc000034538, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3ab28 sp=0xc000a3a9f8 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xdf43c0, 0xc000034538, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3aca0 sp=0xc000a3ab28 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xed34e0, 0xc000034500, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3ae18 sp=0xc000a3aca0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpSlice(0xc000a40ab0, 0xe08780, 0xc00015d718, 0x1b7) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:238 +0x125 fp=0xc000a3af30 sp=0xc000a3ae18 pc=0xd5b845 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe08780, 0xc00015d718, 0x1b7) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:352 +0x9e6 fp=0xc000a3b0a8 sp=0xc000a3af30 pc=0xd5c926 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09da0, 0xc00015d6c0, 0x1f9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3b220 sp=0xc000a3b0a8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09a20, 0xc00015d6c0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3b398 sp=0xc000a3b220 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf6b5a0, 0xc0001db790, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3b4c8 sp=0xc000a3b398 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf6b5a0, 0xc0001db790, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3b640 sp=0xc000a3b4c8 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4d60, 0xc0001db780, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3b7b8 sp=0xc000a3b640 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe93400, 0xc0001db780, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3b930 sp=0xc000a3b7b8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xeb2060, 0xc0001db780, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3baa8 sp=0xc000a3b930 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpSlice(0xc000a40ab0, 0xe087c0, 0xc000198c68, 0x1b7) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:238 +0x125 fp=0xc000a3bbc0 sp=0xc000a3baa8 pc=0xd5b845 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe087c0, 0xc000198c68, 0x1b7) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:352 +0x9e6 fp=0xc000a3bd38 sp=0xc000a3bbc0 pc=0xd5c926 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4ee0, 0xc000198c68, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3beb0 sp=0xc000a3bd38 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4e20, 0xc000198c60, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3c028 sp=0xc000a3beb0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xdf43c0, 0xc000034578, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3c158 sp=0xc000a3c028 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xdf43c0, 0xc000034578, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3c2d0 sp=0xc000a3c158 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xed34e0, 0xc000034540, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3c448 sp=0xc000a3c2d0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf3f340, 0xc000034540, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3c578 sp=0xc000a3c448 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf3f340, 0xc000034540, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3c6f0 sp=0xc000a3c578 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4d60, 0xc0001db740, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3c868 sp=0xc000a3c6f0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe93400, 0xc0001db740, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3c9e0 sp=0xc000a3c868 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xeb2060, 0xc0001db740, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3cb58 sp=0xc000a3c9e0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf23c00, 0xc0001db740, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3cc88 sp=0xc000a3cb58 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf23c00, 0xc0001db740, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3ce00 sp=0xc000a3cc88 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe631c0, 0xc00007c420, 0x1b5) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:394 +0xe25 fp=0xc000a3cf78 sp=0xc000a3ce00 pc=0xd5cd65 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xeb33c0, 0xc00007c420, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3d0f0 sp=0xc000a3cf78 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xefc400, 0xc00007c420, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3d220 sp=0xc000a3d0f0 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xefc400, 0xc00007c420, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3d398 sp=0xc000a3d220 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09e80, 0xc00034d2c0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3d510 sp=0xc000a3d398 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xebb380, 0xc00034d2c0, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3d640 sp=0xc000a3d510 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xebb380, 0xc00034d2c0, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3d7b8 sp=0xc000a3d640 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf33260, 0xc0002488c0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3d930 sp=0xc000a3d7b8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09da0, 0xc0002488c0, 0x1f9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3daa8 sp=0xc000a3d930 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09a20, 0xc0002488c0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3dc20 sp=0xc000a3daa8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf6b5a0, 0xc000196360, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3dd50 sp=0xc000a3dc20 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf6b5a0, 0xc000196360, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3dec8 sp=0xc000a3dd50 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4d60, 0xc000196350, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3e040 sp=0xc000a3dec8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe93400, 0xc000196350, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3e1b8 sp=0xc000a3e040 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xed3ae0, 0xc000196350, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3e330 sp=0xc000a3e1b8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf5fd00, 0xc000196350, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3e460 sp=0xc000a3e330 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf5fd00, 0xc000196350, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3e5d8 sp=0xc000a3e460 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf28880, 0xc0001b6488, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3e750 sp=0xc000a3e5d8 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf6b840, 0xc0001b6488, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3e880 sp=0xc000a3e750 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf6b840, 0xc0001b6488, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3e9f8 sp=0xc000a3e880 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe7f000, 0xc0001161b0, 0x1b5) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:394 +0xe25 fp=0xc000a3eb70 sp=0xc000a3e9f8 pc=0xd5cd65 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf0a200, 0xc0001161b0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3ece8 sp=0xc000a3eb70 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf3f4a0, 0xc0001161b0, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3ee18 sp=0xc000a3ece8 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc0004f6ab0, 0xf3f4a0, 0xc0001161b0, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3ef90 sp=0xc000a3ee18 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf33260, 0xc00015cfc0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3f108 sp=0xc000a3ef90 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09da0, 0xc00015cfc0, 0x1f9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3f280 sp=0xc000a3f108 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf09a20, 0xc00015cfc0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3f3f8 sp=0xc000a3f280 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf6b5a0, 0xc00017b2e0, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3f528 sp=0xc000a3f3f8 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc0004f6ab0, 0xf6b5a0, 0xc00017b2e0, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3f6a0 sp=0xc000a3f528 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef4d60, 0xc00017b2d0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3f818 sp=0xc000a3f6a0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe93400, 0xc00017b2d0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3f990 sp=0xc000a3f818 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xed3ae0, 0xc00017b2d0, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3fb08 sp=0xc000a3f990 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf5fd00, 0xc00017b2d0, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a3fc38 sp=0xc000a3fb08 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc0004f6ab0, 0xf5fd00, 0xc00017b2d0, 0x36) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a3fdb0 sp=0xc000a3fc38 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf28880, 0xc000123148, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a3ff28 sp=0xc000a3fdb0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xf6b840, 0xc000828d80, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a40058 sp=0xc000a3ff28 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc0004f6ab0, 0xf6b840, 0xc000828d80, 0x1b6) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a401d0 sp=0xc000a40058 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef52a0, 0xc000828d80, 0x1b9) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a40348 sp=0xc000a401d0 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xef0620, 0xc000828d80, 0x199) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a404c0 sp=0xc000a40348 pc=0xd5c474 github.com/davecgh/go-spew/spew.(*dumpState).dumpPtr(0xc000a40ab0, 0xee9ea0, 0xc000828d80, 0x16) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:154 +0x7f8 fp=0xc000a405f0 sp=0xc000a404c0 pc=0xd5b5b8 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc0004f6ab0, 0xee9ea0, 0xc000828d80, 0x16) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:262 +0x1765 fp=0xc000a40768 sp=0xc000a405f0 pc=0xd5d6a5 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xe64f00, 0xc0006580c0, 0x95) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:394 +0xe25 fp=0xc000a408e0 sp=0xc000a40768 pc=0xd5cd65 github.com/davecgh/go-spew/spew.(*dumpState).dump(0xc000a40ab0, 0xf73140, 0xc000658000, 0x99) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:421 +0x534 fp=0xc000a40a58 sp=0xc000a408e0 pc=0xd5c474 github.com/davecgh/go-spew/spew.fdump(0x161e140, 0x1111720, 0xc000726630, 0xc000a40c30, 0x1, 0x1) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/dump.go:465 +0x125 fp=0xc000a40af0 sp=0xc000a40a58 pc=0xd5d845 github.com/davecgh/go-spew/spew.(*ConfigState).Sdump(0x161e140, 0xc0004f6c30, 0x1, 0x1, 0x19, 0x0) /root/go/pkg/mod/github.com/davecgh/go-spew@v1.1.1/spew/config.go:281 +0x78 fp=0xc000a40b38 sp=0xc000a40af0 pc=0xd5aa58 github.com/stretchr/testify/assert.diff(0xf73140, 0xc000658000, 0xf73140, 0xc0006581c0, 0x0, 0x0) /root/go/pkg/mod/github.com/stretchr/testify@v1.6.1/assert/assertions.go:1592 +0x1d8 fp=0xc000a40cd8 sp=0xc000a40b38 pc=0xd66e38 github.com/stretchr/testify/assert.Equal(0x1114680, 0xc00054bb00, 0xf73140, 0xc000658000, 0xf73140, 0xc0006581c0, 0xc000a41078, 0x1, 0x1, 0x1)

  • 导入模块开头要大写,不然会报错
cannot refer to unexported name xxxx

错误变量覆盖,深坑,没告警


func (mgr *Manager) fixRunningTask() {
    db := store.GetMongo()
    docs, err := db.GetNoHeartbeatTask()
    if err != nil {
        return
    }
    //proxy连接代码,省略
    for _, doc := range docs {
        task := task.NewTask(doc)
		ErrCount := 0
		var res error
		for {
			err := task.SyncResult(proxy, true, opts...)
			if err == nil || err != ErrSystem {
			// res = task.SyncResult(proxy, true, opts...)
			//if res == nil || res != common.ErrSystem {
				break
			}
			// 如果是框架超时等错误,多试几次
            ErrCount++
            if ErrCount > 10 {
				break
			}
		}
		if err != nil && err != ErrStillRunning {
		// if res != nil && res != ErrStillRunning {
			// 可能发生了迁移或者重启,重新做
            db.InitTask(...)
        }
    }
}

上面的err,覆盖了下面的err。导致永远不会执行InitTask

c/c++程序员习惯于编译器纠错,但go编译器一点反应都没

一个字符数组默认引用的例子

start := Partition.Range.Start
startUint32 := binary.LittleEndian.Uint32(start)
binary.BigEndian.PutUint32(start, startUint32)

这么改,start和 Partition.Range.Start实际上是一个东西

这段代码这么看没啥问题,如果是个复杂一点的逻辑,就会被坑到,比如后面又改了start,但结果把上面的一起改了

go pprof抓内存泄漏

curl localhost:6060/debug/pprof/heap >base.out
# 喝口水,上个厕所
curl localhost:6060/debug/pprof/heap >current.out
go tool pprof -base base.out current.out

# 进入交互
(pprof) top10
(pprof) tree

基本就能查到,还算好用

看懂堆栈

// Declaration
main.Example(slice []string, str string, i int)

// Stack trace
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)

类型 + 长度

参考资料

  • https://chai2010.cn/advanced-go-programming-book/ch1-basic/ch1-03-array-string-and-slice.html
  • https://go-zh.org/doc/effective_go.html
  • https://gfw.go101.org/article/container.html
  • https://go-internals-cn.gitbook.io/go-internals/chapter1_assembly_primer
  • https://www.includehelp.com/golang/how-to-check-if-structure-is-empty.aspx