如何编写一个通用函数,该函数接受一个字符串或一个错误作为参数?

huangapple go评论76阅读模式
英文:

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 := &quot;something was wrong&quot;
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError{reason})

and something like this with errors:

reason := errors.New(&quot;something was wrong&quot;)
c.AbortWithStatusJSON(http.StatusBadRequest, ServerError{reason.Error()})

huangapple
  • 本文由 发表于 2022年10月4日 22:43:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/73949665.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定