我正在使用下面的代码在客户端删除sqs消息。
if resp, err := s.client.DeleteMessageBatch(context.TODO(), &sqs.DeleteMessageBatchInput{
Entries: entries,
QueueUrl: s.url,
}); err != nil {
return fmt.Errorf("failed to DeleteMessageBatch, %v, %v", err, resp.Failed)
}
由于你不需要看整个代码,所以我写了部分代码。
如你所见,当 err 不为 nil 时,我调用了
DeleteMessageBatchInput
并打印了错误消息。
假设调用时出现网络问题,则 err 不为 nil。 在这种情况下,
resp.Failed
可以有空值,从而导致内存问题?
如果是这样,我是否需要为上述情况编写一些防御代码?
任何帮助将不胜感激。
谢谢。
请参阅删除消息批次。
失败有两种情况。
第一个 http 200 和失败的数组。
第二个 http 不是 200,只会出现错误。
所以你可以这样写
resp, err := s.client.DeleteMessageBatch(context.TODO(), &sqs.DeleteMessageBatchInput{
Entries: entries,
QueueUrl: s.url,
})
if err != nil {
return fmt.Errorf("failed to DeleteMessageBatch, %v", err)
}
if len(resp.Failed) > 0 {
return fmt.Errorf("failed to DeleteMessageBatch, %v", resp.Failed)
}
一般来说,约定是当返回错误时,其余值无效。如果您查看代码,您会返回错误或结果:
result, err := ...
if err != nil {
return nil, err
}
...
return result, nil
对于您遇到的任何正常代码来说通常都是如此。
所以你不必在错误情况下测试
resp
任何东西,你根本不应该使用它。您的代码将不可避免地因空指针异常而恐慌。
文档指出,您应该检查对 Client.DeleteMessageBatch
的successful 调用是否存在批处理错误。如果调用失败,您实际上无法确定,因为不清楚错误发生在哪里(例如,批处理可能已成功,但由于网络错误而您没有收到响应)。
如果您有更复杂的错误处理,您可以返回一个错误,表明整个操作失败或哪些条目受到影响。
对于部分失败,定义您自己的错误类型,例如:
type EntryDeletionError struct {
Failed []types.BatchResultErrorEntry
}
func (e EntryDeletionError) Error() string {
var b strings.Builder
b.WriteString("deletion failed for: ")
first := true
for _, f := range e.Failed {
if first {
b.WriteString(", ")
first = false
}
b.WriteString(*f.Id)
}
return b.String()
}
并在你的函数中使用它:
resp, err := s.client.DeleteMessageBatch(context.TODO(), &sqs.DeleteMessageBatchInput{
Entries: entries,
QueueUrl: s.url,
})
switch {
case err != nil:
return fmt.Errorf("deleting entries failed: %w", err)
case len(resp.Failed) > 0:
return EntryDeletionError{resp.Failed}
}
return nil
请注意,您应该用 %w
包裹丰富的错误,而不是
%v
。