英文:
How to convert known type to pointer to type parameter in a switch?
问题
我正在尝试编写一个函数,根据返回值的type参数,将一个JSON字符串的字节数组转换为另一个字节数组,转换规则如下:
- map[string]interface{}:转换为map[string]interface{}
- []byte:不进行转换,原样返回
- struct:转换为struct
我的代码如下:
func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
var buff T
switch any(result).(type) {
case *[]byte:
result = &T(jsonByteArray)
default:
err = json.Unmarshal(jsonByteArray, &buff)
result = &buff
}
return
}
在将jsonByteArray的类型转换为T的类型时,代码出现以下类型错误:
cannot convert jsonByteArray (variable of type []byte) to type T
我该如何将这个**[]byte**类型变量的指针赋值给泛型类型的返回值?
英文:
I'm trying to write a function which converts a byte array of JSON string to another in accordance with the type parameter of the return value as the following rule:
- map[string]interface{}: convert to map[string]interface{}
- []byte: no conversion, return as is
- struct: convert to the struc
My code is as follow:
func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
var buff T
switch any(result).(type) { // https://appliedgo.com/blog/a-tip-and-a-trick-when-working-with-generics
case *[]byte:
result = &T(jsonByteArray)
default:
err = json.Unmarshal(jsonByteArray, &buff)
result = &buff
}
return
}
This code occurs following type error at the point of cast the type of jsonByteArray to T as follows:
cannot convert jsonByteArray (variable of type []byte) to type T
How can I assign the pointer of this []byte type variable to the generic type return value?
答案1
得分: 5
由于T
受到any
的限制,你不能直接转换。你必须断言&jsonByteArray
在switch case中确实是与*T
相同的类型:
func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
var buff T
switch any(result).(type) {
case *[]byte:
result = any(&jsonByteArray).(*T)
default:
err = json.Unmarshal(jsonByteArray, &buff)
result = &buff
}
return
}
这样可以消除编译错误,但这并不是特别好的设计。如果你只需要为一个类型(*[]byte
)专门定制json.Unmarshal
,最好是改变调用点而不是使用通用函数。
我假设你的目标是允许调用者获取字节切片而不是解组。那么在调用点,你可以这样调用函数:
data := GetJsonData[[]byte](jsonByteArray)
这意味着在那一点上你已经知道jsonByteArray
是一个字节切片。
然后,没有理由调用该函数。你可以简单地取参数的地址:data := &jsonByteArray
,并在其他地方使用json.Unmarshal
。
英文:
Since T
is constrained by any
, you can’t directly convert. You have to assert that &jsonByteArray
is really the same type as *T
in that switch case:
func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
var buff T
switch any(result).(type) {
case *[]byte:
result = any(&jsonByteArray).(*T)
default:
err = json.Unmarshal(jsonByteArray, &buff)
result = &buff
}
return
}
This makes the compile error go away, however it isn’t particularly good design. If you need to specialize json.Unmarshal
for only one type (*[]byte
) you are better off changing the call sites instead of using a generic function.
I assume that your goal is to allow callers to get the byte slice as is, instead of unmarshalling. Then at call site you would call the function as
data := GetJsonData[[]byte](jsonByteArray)
This means that at that point you already know that jsonByteArray
is a byte slice.
Then, there’s no reason to call the function. You can simply take the address of the argument: data := &jsonByteArray
, and use json.Unmarshal
everywhere else.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论