Go 问题请教

323 天前
 folivora

有大佬可以帮忙看看 SendToProc 这个函数里 select+slice 会 panic 吗?感谢感谢🙏

func init() {
	Chan = make(chan *GenData, 500000)
}

var Chan chan *GenData

type SendQueue struct {
	queue []*GenData
	size  int
}

type GenData struct {
	s string
}

func SendToProc() error {
	go func() {
		batchSize := 100
		tc := time.NewTicker(time.Millisecond * 100)
		sq := &SendQueue{
			queue: make([]*GenData, 0),
			size:  0,
		}
		for {
			select {
			case g := <-Chan:
				sq.queue = append(sq.queue, g)
				sq.size++
				if sq.size == batchSize {
					send(sq.queue)
					sq.queue = sq.queue[:0]
					sq.size = 0
				}
			case <-tc.C:
				if sq.size > 0 {
					send(sq.queue)
					sq.queue = sq.queue[:0]
					sq.size = 0
				}
			}
		}
	}()
	return nil
}

func send(sendList []*GenData) {
	for i, v := range sendList {
		fmt.Println(i, v)
	}
}

1332 次点击
所在节点    Go 编程语言
11 条回复
iyear
323 天前
不太知道你觉得 panic 的点在哪里
folivora
323 天前
@iyear #1 担心数组越界 panic ,我怀疑,代码能力太差了
iyear
323 天前
浅看了一下,没有可能造成越界的代码,所以越界肯定不会。不过这个 size ,用 len 代替不好么,同时维护一致性上容易疏忽。
folivora
323 天前
@iyear #3 感谢大佬,我回头优化下代码 hh
chenxiankong
323 天前
没看出 panic 点,要不把 panic 报错和具体代码行发一下?
AnroZ
323 天前
建议:
1. 增加下 goroutine 循环退出的响应
2. 习惯性的在这种 goroutine 函数增加一个 defer 函数 处理下异常
3. len 替换 size
4. 收不到 g chan 100 毫秒后再触发超时是不是更合理些,没必要周期性定时 100 毫秒
folivora
323 天前
@chenxiankong #5 主要是进程挂了,怀疑这个地方有问题 panic 了,想请诸位大佬人眼 debug 下。
iyear
323 天前
@AnroZ #6 他的 ticker 作用应该不是超时,他应该是想某个时间段内没达到 batchSize 也发出去防止存留太久
folivora
323 天前
@iyear #8 是的,ticker 主要是控制了发送策略,达到 batchSize 或者每隔 0.1s 发送一次。
MoYi123
323 天前
虽然是一样的, sq.size == batchSize 还是写 sq.size >= batchSize 看着安心一点.
pkoukk
323 天前
6# 比较完整了。
一般我们会在 SendQueue 里加一个 context ,select 的时候加一项 ctx.Done()当做退出信号,清空队列里的数据,防止主进程退出时,队列里有东西没被处理掉。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/950468

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX