接触到golang后,最让我困惑的就是reflect/interface。下面通过一个例子来试着理解一下。
golang/dlv环境搭建参考这里
先上源码
package main
import (
"fmt"
"reflect"
)
func main() {
test := []map[string]interface{}{{"abc":"3","xyz":"4"},{"abc":"1","xyz":"5"}}
Pass(test)
}
func Pass(d interface{}) {
eleMapKey := "abc"
var eleMapOther string
if reflect.TypeOf(d).Kind() == reflect.Slice {
s := reflect.ValueOf(d)
for i := 0; i < s.Len(); i++ {
ele := s.Index(i)
eleMapKeyValue := ele.MapIndex(reflect.ValueOf(eleMapKey))
eleIntf := ele.Interface()
eleMap,ok := eleIntf.(map[string]interface{})
if ok {
for k,v := range eleMap {
if k == eleMapKey {
continue
}
eleMapOther = fmt.Sprintf("%v",v.(string))
}
}
fmt.Printf("[%v:%v]\n",eleMapKeyValue,eleMapOther)
}
}
}
试着理解
- line 1:golang可以将一个完整功能的实现,拆分到不同的go源代码文件中,只要这些文件起始的package是一样的,但是main()函数只能有一个,作为整个功能的唯一入口
- import就是导入已有的包,不需要重复造轮子
- main()中的定义的test数据,本身是一个slice,每个slice的元素是一个map,而map是从string映射到interface{}。本例中的interface指向的就是最基础的string
- line 17是非常关键的一步,reflect.Value 表示 interface{} 里存储的实际变量,用来将interface{}转为slice,就可以逐个取出处理了
- line 20是获取eleMapKey对应的value,因为此时不是直接的string map string,所以要这样来写
- line 21通过.interface(),将value还原回interface
- line 22 通过.map彻底还原为map结果,下面的就是对map进行正常的遍历和处理了
编译执行
admin@ubuntu20:~/go$ go build -gcflags '-N -l' intf_demo.go
admin@ubuntu20:~/go$ ./intf_demo
[3:4]
[1:5]
admin@ubuntu20:~/go$