英文:
Generics with nested maps
问题
目前我正在使用类似这样的代码:
package hello
type object map[string]interface{}
func (o object) get(key string) object {
val, _ := o[key].(object)
return val
}
func (o object) getInt(key string) int {
val, _ := o[key].(int)
return val
}
但问题是,我必须为每种要返回的类型编写一个函数。我尝试使用类似这样的代码:
package hello
type object map[string]interface{}
// 语法错误:方法不能有类型参数
func (o object) get[T object|int](key string) T {
val, _ := o[key].(T)
return val
}
然后我尝试了这样的代码:
package hello
type object map[string]interface{}
type token[T object|int] struct {
in object
out T
}
func (t token[T]) get(key string) token[T] {
t.out, _ = t.in[key].(T)
return t
}
这段代码可以编译通过,但由于in
从未更新,我认为我无法进行链式调用,例如对于嵌套的映射:
something.get("one").get("two").get("three")
是否有可能使用泛型来实现与我的原始代码类似的结果,但不需要复制粘贴函数?
英文:
Currently I am using some code like this:
package hello
type object map[string]interface{}
func (o object) get(key string) object {
val, _ := o[key].(object)
return val
}
func (o object) getInt(key string) int {
val, _ := o[key].(int)
return val
}
but the issue is, I have to write a function for every type I want to return. I
tried using something like this:
package hello
type object map[string]interface{}
// syntax error: method must have no type parameters
func (o object) get[T object|int](key string) T {
val, _ := o[key].(T)
return val
}
then I did this:
package hello
type object map[string]interface{}
type token[T object|int] struct {
in object
out T
}
func (t token[T]) get(key string) token[T] {
t.out, _ = t.in[key].(T)
return t
}
which compiles, but since in
never gets updated, I don't think I could do chaining, for a nested map:
something.get("one").get("two").get("three")
Is it possible to do something with generics, to give a similar result to my original code, but without having the copy paste functions?
答案1
得分: 1
我想我弄明白了。你可以创建一个包装类型,它包含当前对象以及输出值。如果有其他想法,我也很感兴趣:
package main
type object map[string]interface{}
type token[T any] struct {
object
value T
}
func newToken[T any](m object) token[T] {
return token[T]{object: m}
}
func (t token[T]) get(key string) token[T] {
switch val := t.object[key].(type) {
case object:
t.object = val
case T:
t.value = val
}
return t
}
示例:
package main
func main() {
obj := object{
"one": object{
"two": object{"three": 3},
},
}
three := newToken[int](obj).get("one").get("two").get("three")
println(three.value == 3)
}
英文:
I think I figured it out. You can create a wrapper type, that holds the current
object, as well as the output value. If anyone has other ideas, I am interested
in them as well:
package main
type object map[string]interface{}
type token[T any] struct {
object
value T
}
func newToken[T any](m object) token[T] {
return token[T]{object: m}
}
func (t token[T]) get(key string) token[T] {
switch val := t.object[key].(type) {
case object:
t.object = val
case T:
t.value = val
}
return t
}
Example:
package main
func main() {
obj := object{
"one": object{
"two": object{"three": 3},
},
}
three := newToken[int](obj).get("one").get("two").get("three")
println(three.value == 3)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论