英文:
How to serialize and deserialize errors string in go
问题
在两个Go服务共享相同类型的情况下,一个客户端向服务器发送一个JSON:
type Message struct {
Error string `json:"error"`
}
客户端应该将一个error
序列化为一个字符串。
服务器应该将该字符串反序列化为一个error
,以便我可以使用errors.As
或errors.Is
来检查包装错误等。
我如何序列化嵌套错误?
英文:
In the context of two go services sharing the same types, one client post a json to a server:
type Message struct {
Error string `json:"error"`
}
The client should serialize an error
into a string.
The server should deserialize that string into an error
on which I can use errors.As
or errors.Is
to check for wrapped errors and such.
How may I serialize nested errors ?
答案1
得分: 1
让我与你分享一些思考,也许可以指导你朝正确的方向前进。
errors.Is
和 errors.As
这两个操作符用于处理 error
类型。它们通常用于处理函数返回的 error
,并根据错误类型采取相应的操作。如果你的函数只返回一个字符串,那么几乎不可能使用 errors.Is
和 errors.As
,除非你进行额外的逻辑处理字符串。
一个简单的解决方法
如果你想保留错误的层次结构而不必将其展平,可以采用以下方法:
package main
import (
"encoding/json"
"fmt"
)
type RecursiveErr struct {
Message string `json:"Message"`
Err error `json:"error"`
}
func (r RecursiveErr) Error() string {
return r.Message
}
func main() {
// 递归 - 编组
childErr := RecursiveErr{Message: "leaf-child error"}
parentErr := RecursiveErr{Message: "root error", Err: &childErr}
data, _ := json.MarshalIndent(&parentErr, "", "\t")
fmt.Println(string(data))
// 递归 - 解组
var parsedParentErr RecursiveErr
json.Unmarshal(data, &parsedParentErr)
fmt.Println(parsedParentErr.Message)
}
这个解决方案有以下好处:
- 你可以保留错误的层次结构(父子关系)。
- 你可以在
Err
字段上调用errors.Is
和errors.As
。
由于这对我来说是一个不常见的场景,希望我的回答没有偏离你的问题,如果有其他需要,请告诉我!
英文:
Let me share with you some thoughts that maybe can guide you in the right direction.
errors.Is
and errors.As
These two operators deal with the error
type. The common scenario they are used when you've to deal with an error
returned by a function and, based on which type of error it is, take some actions. If you're returning just a string from a function, it's almost impossible to invoke errors.Is
and errors.As
unless you do some extra logic to handle the string.
A simple workaround
If you wanna preserve a hierarchical structure for your errors without having to flatten them, you could follow this approach:
package main
import (
"encoding/json"
"fmt"
)
type RecursiveErr struct {
Message string `json:"Message"`
Err error `json:"error"`
}
func (r RecursiveErr) Error() string {
return r.Message
}
func main() {
// recursive - marshal
childErr := RecursiveErr{Message: "leaf-child error"}
parentErr := RecursiveErr{Message: "root error", Err: &childErr}
data, _ := json.MarshalIndent(&parentErr, "", "\t")
fmt.Println(string(data))
// recursive - unmarshal
var parsedParentErr RecursiveErr
json.Unmarshal(data, &parsedParentErr)
fmt.Println(parsedParentErr.Message)
}
This solution has the following benefits:
- You can preserve the hierarchical structure of your errors (parent-child relationship)
- You can invoke the
errors.Is
anderrors.As
on theErr
field.
As it's an uncommon scenario for me, I hope to not be off-topic with your request, let me know!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论