英文:
How to write a generic function that takes a string or an error as a parameter?
问题
有没有办法将字符串或错误作为泛型参数?
上面的代码包含一个辅助函数,尝试使用一个包含一个泛型字段的 JSON 响应一个 HTTP 请求,我希望该字段可以是一个 string
或一个 error
。
但是当我尝试输入一个字符串时:
string does not implement fmt.Stringer (missing method String)
我觉得这非常有趣。
我尝试将 T fmt.Stringer
改为 T string | fmt.Stringer
:
cannot use fmt.Stringer in union (fmt.Stringer contains methods)
我理解的原因是,在 Go 语言中,string
是一个没有任何方法的原始数据类型,我想知道是否有可能实现这个目标。
更新:
正如 @nipuna 在评论中指出的,error
也不是 Stringer
。
英文:
Is there any way to take a string or an error as a generic parameter?
package controller
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type ServerError[T fmt.Stringer] struct {
Reason T `json:"reason"`
}
func ResponseWithBadRequest[T fmt.Stringer](c *gin.Context, reason T) {
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError[T]{Reason: reason})
}
The above code contains a helper function tries to response an http request with a json containing one generic field that I would like it to be a string
or an error
.
But when I try to input a string:
string does not implement fmt.Stringer (missing method String)
which I find very amusing.
I tried to change T fmt.Stringer
to T string | fmt.Stringer
:
cannot use fmt.Stringer in union (fmt.Stringer contains methods)
I understand the reason is that string
in golang is a primitive data type without any method, I would like to know if there's a possible way to do this.
Update:
As @nipuna pointed out in the comment, error
is not a Stringer
either.
答案1
得分: 2
有没有办法将字符串或错误作为泛型参数?
没有。正如所述,你要找的约束是~string | error
,但这是行不通的,因为带有方法的接口不能用于联合类型。
而error
确实是一个带有Error() string
方法的接口。
处理这个问题的明智方法是放弃泛型,将Reason
定义为string
:
type ServerError struct {
Reason string `json:"reason"`
}
你可以在这里找到更多详细信息:https://stackoverflow.com/questions/44989924/golang-error-types-are-empty-when-encoded-to-json。简而言之,error
不能直接编码为JSON;你最终还是要提取它的字符串消息。
所以最终你会像这样处理字符串:
reason := "something was wrong"
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError{reason})
以及像这样处理错误:
reason := errors.New("something was wrong")
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError{reason.Error()})
英文:
> Is there any way to take a string or an error as a generic parameter?
No. As stated, the constraint you are looking for is ~string | error
, which doesn't work because interfaces with methods can't be used in unions.
And error
is indeed an interface with the Error() string
method.
The sensible way to handle this is to drop generics and define Reason
as a string
:
type ServerError struct {
Reason string `json:"reason"`
}
You can find more details about that here: https://stackoverflow.com/questions/44989924/golang-error-types-are-empty-when-encoded-to-json. The tl;dr is that error
<strike>can't</strike> shouldn't be encoded to JSON directly; you'll eventually have to extract its string message anyway.
So in the end you're going to do something like this with strings:
reason := "something was wrong"
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError{reason})
and something like this with errors:
reason := errors.New("something was wrong")
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError{reason.Error()})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论