如何在1.18中使用golang泛型来简化代码片段?

我一直在使用 2 个由OpenAPI 生成器在单独的包中生成的 SDK,它们共享在不同包中重复的相同代码foobar

package foo

// there's the exact same piece of code under another package bar


// GenericOpenAPIError Provides access to the body, error and model on returned errors.

type GenericOpenAPIError struct {

    ...

    model interface{}

}


// Model returns the unpacked model of the error

func (e GenericOpenAPIError) Model() interface{} {

    return e.model

}


// Failure Provides information about problems encountered while performing an operation.

type Failure struct {

    // List of errors which caused this operation to fail

    Errors []Error `json:"errors"`

}


// GetErrors returns the Errors field value

func (o *Failure) GetErrors() []Error {...}


// Error Describes a particular error encountered while performing an operation.

type Error struct {

    ...

    // A human-readable explanation specific to this occurrence of the problem.

    Detail *string `json:"detail,omitempty"`

    ...

}

另外,有一个应用程序,我在其中使用了两个 SDK:,并从错误列表foo中bar提取了第一个错误,我在其中尝试将错误转换为每个 SDK 的错误类型,因此必须复制代码。1.18有没有一种方法可以使用支持泛型的方法来简化它?


慕桂英546537
浏览 77回答 1
1回答

Cats萌萌

您可以更改mainErrorModel为struct with no pointer带有类型断言,然后将该结构更改为struct with pointer,最后您可以再次更改为Failure带有类型断言的类型接口。这是例子。// You can edit this code!// Click here and start typing.package mainimport (    "fmt")type GenericOpenAPIError interface {    Model() any}type Failure interface {    GetErrors() string}type GenericOpenAPI struct {    model any}func (g *GenericOpenAPI) Model() any {    return g.model}func (g *GenericOpenAPI) Error() string {    return "goae error"}type A struct {    b string}func (a *A) GetErrors() string {    return a.b}type B struct {    c string}func (b *B) GetErrors() string {    return b.c}type GetErrores interface {    A | B}func getErrorMessage[T GetErrores](err error) string {    if mainError, ok1 := err.(GenericOpenAPIError); ok1 {        var mainErrorModel = mainError.Model()        if t, ok := mainErrorModel.(T); ok {            if f, ok := any(&t).(Failure); ok { // must change &t to any then type assert to Failure to tell app that there is a method GetErrors()                return f.GetErrors()            }        }    }    return err.Error()}func main() {    var err any    err = &GenericOpenAPI{A{b: "this is error a"}}    e, ok := err.(error)    if !ok {        panic("not ok!")    }    fmt.Println(getErrorMessage[A](e))    // change model to B    err = &GenericOpenAPI{B{c: "this is error b"}}    e, ok = err.(error)    if !ok {        panic("not ok!")    }    fmt.Println(getErrorMessage[B](e))}
打开App,查看更多内容
随时随地看视频慕课网APP