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

在结构中使用通用切片字段

在结构中使用通用切片字段

Go
aluckdog 2022-10-04 14:19:46
我们希望拥有type ResponseListDataPayload struct {    List     []*interface{} `json:"list"` //generic    TotalCnt int64          `json:"totalCnt"`    Page     int64          `json:"page"`    Step     int64          `json:"step"`}并且可以接受List[]*model.SomeModel{}queryResults := []*model.SomeModel{}resposeResult := &ResponseListDataPayload{    List:     queryResults,    TotalCnt: cnt,    Page:     pageInt,    Step:     stepInt,}或[]*model.AnotherModel{}queryResults := []*model.AnotherModel{}resposeResult := &ResponseListDataPayload{    List:     queryResults,    TotalCnt: cnt,    Page:     pageInt,    Step:     stepInt,}这在Java中非常简单,这在Go中可能吗?
查看完整描述

2 回答

?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

前往 1.18

您现在可以拥有参数化结构:


type ResponseListDataPayload[T any] struct {

    List     []T            `json:"list"` //generic

    TotalCnt int64          `json:"totalCnt"`

    Page     int64          `json:"page"`

    Step     int64          `json:"step"`

}

请记住,泛型结构必须使用显式类型参数进行实例化:


queryResults := []*model.SomeModel{}

responseResult := &ResponseListDataPayload[*model.SomeModel]{

    List:     queryResults,

    // other fields

}

如果你想进一步提高代码重用率,并“泛化”结构初始化,你可以使用构造函数。函数可以利用类型推断来省略写出类型参数:


// add to func signature other arguments as needed

func NewResponseFor[T any](list []T) *ResponseListDataPayload[T] {

    return &ResponseListDataPayload[T]{ List: list }

}

并将其用作:


queryResults := // some query results

responseResult := NewResponseFor(queryResults)

示例:https://gotipplay.golang.org/p/jYTHegaeubR


前往 1.17 及以下

这在围棋中是可能的吗?


不,实际上不是泛型类型,它只是一个具有空方法集的接口。interface{}


形式上,您可以为其分配任何具体值,因为可赋值性要求值的方法集是接口方法集的超集,并且任何集都是空集的超集 ()。∅


它与像Java这样的参数化类型不是一回事,因此在Go中不能分配给。List<T>[]Foo[]interface{}


您必须在循环中处理单个元素:


var m []*model.anotherModel

// populate m

for _, v := range m {

    resp.List = append(resp.List, v)

}

同样,不要使用指向空接口 的指针。请改用。*interface{}interface{}


如果您的目标只是序列化 JSON(基于结构上是否存在标记),则可以将字段声明为,并且出于上述原因,您可以将任一切片值分配给它。从而避免了额外的切片操作。然后,json 包将根据 中框出的具体值进行序列化。Listinterface{}interface{}


查看完整回答
反对 回复 2022-10-04
?
MMTTMM

TA贡献1869条经验 获得超4个赞

在 Go 1.18 中,您将能够使用真正的 go 泛型来执行类似操作:


func convert[S any](src []S) []interface{} {

    dst := make([]interface{}, 0, len(src))

    for _, v := range src {

        dst = append(dst, v)

    }

    return dst

}

//...

resp.List = convert(m)

但是,在 1.18 发布并且更多的代码库包含泛型之前,您仍然需要手动进行转换。


就像大家说的,不要使用.*interface{}


查看完整回答
反对 回复 2022-10-04
  • 2 回答
  • 0 关注
  • 70 浏览
慕课专栏
更多

添加回答

举报

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