问题描述
我有一个创建user -> user job -> user contact
的服务,并且为了用户的工作和联系,我通过包装go goroutine来包装他们的任务,
// create the user first.....
// then
go func() {
clientJob.UserID = user.ID
_,err = s.userJobRepository.Create(ctx,*clientJob)
if err != nil {
panic(err)
}
clientContact.UserID = user.ID
_,err = s.userContactRepository.Create(ctx,clientContact)
if err != nil {
panic(err)
}
}()
我在该goroutine中获得了context canceledpanic
,之后我的服务器停止了,但是如果我不使用goroutine,那很好,在创建过程中也没有错误,
有谁知道为什么会这样以及如何处理?
解决方法
每个 goroutine 都有自己的堆栈。如果堆栈没有恢复,程序将悲惨地退出。建议:不要使用 panic 来控制业务逻辑。
问题是:为什么?如果 userJobRepository.Create
或 userContactRepository.Create
失败,用户将永远不会知道它,您的服务器就会死机。
我可以看到以下2个选项:
选项1:
您可以为go例程创建一个新的上下文,而不是使用已经与父go例程相关联的上下文。
CREATE TABLE things(
id SMALLSERIAL PRIMARY KEY,name varchar UNIQUE
);
选项2:
如果需要从父级继承值,则上下文将需要通过以下方法实现context.Context接口:
INSERT INTO things (name)
VALUES ('desk')
ON CONFLICT DO NOTHING;