为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕桂英546537 2022-11-23 16:04:20

我一直在使用 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有没有一种方法可以使用支持泛型的方法来简化它?


查看完整描述

1 回答

?
Cats萌萌

TA贡献1536条经验 获得超9个赞

您可以更改mainErrorModel为struct with no pointer带有类型断言,然后将该结构更改为struct with pointer,最后您可以再次更改为Failure带有类型断言的类型接口。


这是例子。


// You can edit this code!

// Click here and start typing.

package main


import (

    "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))

}


查看完整回答
反对 回复 2022-11-23

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信