Go 的范型怎么把 Response[指定类型] 转换为 Response[any]

2023-01-28 10:52:36 +08:00
 jorneyr

问题: Go 的范型怎么把 Response[指定类型] 转换为 Response[any].

下面的示例代码在 [3] 部分进行类型转换的时候报错 cannot use rsp2 (variable of type Response[map[string]string]) as Response[any] value in assignment 。

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
}
2696 次点击
所在节点    程序员
29 条回复
we8105
2023-01-28 14:13:43 +08:00
我也有类似的问题
jorneyr
2023-01-28 14:27:36 +08:00
@kaf 与你的思路还是不太一样的。
exonuclease
2023-01-28 14:51:39 +08:00
Response<T>不能直接用吗 c#里面是可以的啊 比如这个函数
private static TValue getValue<Tkey,TValue>(KeyValuePair<Tkey,TValue> kvp)
{
return kvp.Value;
}
jorneyr
2023-01-28 15:19:26 +08:00
@exonuclease 在 go 里不可以呢。
BeautifulSoap
2023-01-28 16:19:24 +08:00
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 目前的泛型并不是完整功能的泛型,所以并不能做到其他教程里那样理所当然的事情
https://www.v2ex.com/t/844084
BeautifulSoap
2023-01-28 16:20:35 +08:00
@BeautifulSoap 打错字“go 目前的泛型并不是完整功能的泛型,所以并不能做到其他语言里那样理所当然的事情”
jorneyr
2023-01-28 16:37:16 +08:00
@BeautifulSoap
嗯,那我这个想统一处理的方式,还想接口好看,在 go 里估计就行不通了。
lazyfighter
2023-01-29 14:50:53 +08:00
我在想 java 是因为任意的对象都继承自 object ,所以泛型 T 不指定就变成了 Object 引用,即父类指向子类引用, 所以感觉 go 里面应该用 interface ,纯属猜测
jorneyr
2023-01-29 15:34:21 +08:00
@lazyfighter 用 interface 的话,我这个场景的统一返回对象直接不使用范型就可以了。

type Response struct {
Code int `json:"code"` // 业务逻辑相关的 code ,不是 HTTP Status Code
Success bool `json:"success"` // 业务逻辑处理成功时为 true ,错误时为 false
Msg string `json:"msg"` // 请求的描述
Data any `json:"data,omitempty"` // 请求的 payload
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/910999

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX