type Obj map[interface{}]interface{}
type JSON map[string]interface{}
func foo(s interface{}) {
switch s.(type) {
case Obj:
s = s.(Obj)
case JSON:
s = s.(JSON)
}
for k, v := range s {
// do sth
}
}
上面的情况会报cannot range over obj (type interface {})
那么这种情况该怎么写,是不是只能把后面 range 的处理逻辑写在 case 里了,像这样:
case Obj:
for k, v := range s.(Obj) {}
假如共用的代码段太长,这样岂不是太难看了
1
ypcs03 2019 年 8 月 27 日 via Android
你确定 interface 能当作 key ?
|
3
mornlight 2019 年 8 月 27 日
目测一下放 switch 外面不行,外面的 s 还是 interface{},k, v 推断不出来类型了。
|
4
Vegetable 2019 年 8 月 27 日
golang 是静态类型,所以你没办法改变对象的类型,只能改变他的值。
s 是 interface{},那他在作用域中就永远是 interface 了。你这个写法就算是放在 switch 里边也不能 for,因为 s 依然还是 interface{},必须是在 switch 里指定一个新的值才行。 |
5
SuperMild 2019 年 8 月 27 日
这句
case Obj: for k, v := range s.(Obj) {} 你把 s 后面的 ".(Obj)" 删掉试试,隐约记得是可以的。 |
6
whoami9894 OP |
7
whoami9894 OP @SuperMild
不行的,`cannot range over interface{}` |
8
SuperMild 2019 年 8 月 27 日
你用了 interface{} 做 key,因此这个 key 也需要断言,让它落实到一个 comparable 类型才行的。
map keys may be of any type that is comparable. |
9
SuperMild 2019 年 8 月 27 日
是稍麻烦一点,先忍一忍吧,Go 很快就有泛型了。
|
10
reus 2019 年 8 月 27 日
type Obj map[interface{}]interface{}
type JSON map[string]interface{} func foo(s interface{}) { do := func(k interface{}, v interface{}) { // do something } switch s := s.(type) { case Obj: for k, v := range s { do(k, v) } case JSON: for k, v := range s { do(k, v) } } } |
11
whoami9894 OP @reus
这样可以解决,学到了 |
12
zzlettle 2019 年 8 月 27 日
没看懂
|
13
SuperMild 2019 年 8 月 27 日
原来是这里漏了赋值(捂脸哭着笑) switch s := s.(type)
|
14
GreatHumorist 2019 年 8 月 27 日
定义接口实现接口,每个类型都实现一个 foo 方法,类似 json 的 unmarshal
|
15
whoami9894 OP @SuperMild
嗯。。我傻了,但赋了值也只在 switch 内可见,还是得在 switch 里写处理逻辑 |
16
whoami9894 OP @GreatHumorist
分别定义 method 还是会导致冗余代码 |