Go 的范型怎么把 Response[指定类型] 转换为 Response[any]
<p>问题: Go 的范型怎么把 Response[指定类型] 转换为 Response[any].</p>
<p>下面的示例代码在 [3] 部分进行类型转换的时候报错 cannot use rsp2 (variable of type Response[map[string]string]) as Response[any] value in assignment 。</p>
<pre><code class="language-go">package main
import (
"encoding/json"
"fmt"
)
type Response[T any] struct {
Code int `json:"code"` // 业务逻辑相关的 code ,不是 HTTP Status Code
Success bool `json:"success"` // 业务逻辑处理成功时为 true ,错误时为 false
Msg string `json:"msg"` // 请求的描述
Data T `json:"data,omitempty"` // 请求的 payload
}
func main() {
}
func foo[T any]() Response[any] {
// [1] 创建范型对象
rsp1 := Response[map[string]string]{
Code: 200,
Success: true,
Data: map[string]string{"1": "one", "2": "two"},
}
// [2] 范型序列化
b, _ := json.Marshal(rsp1)
fmt.Println(string(b))
// [3] 范型反序列化
var rsp2 Response[map[string]string]
json.Unmarshal(b, &rsp2)
fmt.Printf("%+v\n", rsp2)
// [4] 范型向上类型转换
// 相当于 Java 的范型用 ? 来接收任意类型的范型如
// List<String> list1 = new LinkedList<>();
// List<?> list2 = list1;
rsp3 := Response[any]{}
rsp3 = rsp2 // 错误: cannot use rsp2 (variable of type Response[map[string]string]) as Response[any] value in assignment
return rsp3
}
</code></pre>
收藏(0 )
分享
相关标签:
注意:本文归作者所有,未经作者允许,不得转载
25个回复
2023年1月28日 03:26
返回 Response[T]
0
0
2023年1月28日 03:26
func (x *Response[T]) ToAny() Response[any] {
return Response[any]{
Code: x.Code,
Success: x.Success,
Msg: x.Msg,
Data: x.Data,
}
}
0
0
2023年1月28日 03:26
你都上泛型了为啥要 any……是不是跑偏了
0
0
2023年1月28日 03:26
谢谢,返回前调用这个方法转换一下能满足要求。
0
0
2023年1月28日 03:26
最快的方法就是做个 copy
0
0
2023年1月28日 03:26
func foo[T any](in T) Response[T] {
// [1] 创建范型对象
rsp1 := Response[T]{
Code: 200,
Success: true,
Data: in,
}
return rsp1
}
你是说这样的功能吗,go 的泛型使用就是你确定入参和返回类型的情况下
0
0
2023年1月28日 03:56
// 像下面这样,接收 Response[string], Response[int] 等任意类型的范型参数进行统一处理。
// 业务代码里可能生成 Response[string], Response[AgentStats] 等不同类型的响应对象,这些对象都会在下面的 responseCommonHandle 函数中统一处理例如某些情况下打印日志。
func responseCommonHandle(rsp Rsponse[any]) {
}
0
0
2023年1月28日 03:56
func main() {
// 返回数据
var (
response1 = Response[map[string]string]{} // 返回 1, 数据类型 map[string]string
response2 = Response[map[int]int]{} // 返回 2, 数据类型 map[int]int
// ...
)
// 模拟接收到的数据
var (
body1, _ = json.Marshal(response1)
body2, _ = json.Marshal(response2)
)
// 解析
var (
result1, err1 = foo[map[string]string](body1) // 指定 T 类型为 map[string]string
result2, err2 = foo[map[int]int](body2) // 指定 T 类型为 map[int]int
)
fmt.Println(result1, err1)
fmt.Println(result2, err2)
}
func foo[T any](body []byte) (response Response[T], err error) {
err = json.Unmarshal(body, &response)
return
}
在调用 foo 时指定类型,看看这样满不满足要求
0
0
2023年1月28日 03:56
```
// [4] 范型向上类型转换
// 相当于 Java 的范型用 ? 来接收任意类型的范型如
// List<String> list1 = new LinkedList<>();
// List<?> list2 = list1;
rsp3 := Response[any]{Code: rsp2.Code, Success: rsp2.Success, Data: rsp2.Data}
```
0
0
2023年1月28日 03:56
下面这段代码是否是你想要的功能
```
package main
// 定义一个结构体,Data 是一个泛型接口
type Response[T ResponseHandle] struct {
Code int `json:"code"` // 业务逻辑相关的 code ,不是 HTTP Status Code
Success bool `json:"success"` // 业务逻辑处理成功时为 true ,错误时为 false
Msg string `json:"msg"` // 请求的描述
Data T `json:"data,omitempty"` // 请求的 payload
}
type ResponseHandle interface {
log()
}
type AgentStats struct {
Status int
}
func (r *AgentStats) log() {
// do something
}
func main() {
}
// 输入泛型的 resp,在函数中执行相关的方法
func responseCommonHandle[T ResponseHandle](rsp Response[T]) {
rsp.Data.log()
}
```
0
0
2023年1月28日 03:56
可以看 go 实现 Java 的 stream 的 map 方法
// Map manipulates a slice and transforms it to a slice of another type.
// Play:
func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {
result := make([]R, len(collection))
for i, item := range collection {
result[i] = iteratee(item, i)
}
return result
}
0
0
2023年1月28日 06:29
我也有类似的问题
0
0
2023年1月28日 06:29
与你的思路还是不太一样的。
0
0
2023年1月28日 08:26
Go 的泛型类型都必须经过实例化。泛型实例化之后的类型就成为了和 int, string, float32 这些类型一样确定的类型
你用 map[string]string 实例化泛型类型 Response[T] 的话,那么实例化之后的类型就是 Response[map[string]string]。用 any 实例化的话实例化得到的则是 Response[any]。编译器的类型检查是不会去关心你这泛型类型到底是怎么个结构的,所以你把一个 Response[map[string]string] 类型的变量赋值给另一个 Response[any] 类型的变量那肯定要报错(在编译器的眼里,这相当于你把 int 类型变量赋值给 string 变量一样)
有兴趣可以看看我之前写的关于泛型的教程,go 目前的泛型并不是完整功能的泛型,所以并不能做到其他教程里那样理所当然的事情
0
0