Foreword: I optimized and improved the below solution, and released it as a library here: github.com/icza/dyno.


The cleanest way would be to create predefined types (structures struct) that model your JSON, and unmarshal to a value of that type, and you can simply refer to elements using Selectors (for struct types) and Index expressions (for maps and slices).

However if your input is not of a predefined structure, I suggest you the following 2 helper functions: get() and set(). The first one accesses (returns) an arbitrary element specified by an arbitrary path (list of string map keys and/or int slice indices), the second changes (sets) the value specified by an arbitrary path (implementations of these helper functions are at the end of the answer).

You only have to include these 2 functions once in your project/app.

And now using these helpers, the tasks you want to do becomes this simple (just like the python solution):

  1. fmt.Println(get(d, "key3", 0, "c2key1", "c3key1"))
  2. set("NEWVALUE", d, "key3", 0, "c2key1", "c3key1")
  3. fmt.Println(get(d, "key3", 0, "c2key1", "c3key1"))

Output:

  1. change1
  2. NEWVALUE

Try your modified app on the Go Playground.

Note - Further Simplification:

You can even save the path in a variable and reuse it to simplify the above code further:

  1. path := []interface{}{"key3", 0, "c2key1", "c3key1"}
  2. fmt.Println(get(d, path...))
  3. set("NEWVALUE", d, path...)
  4. fmt.Println(get(d, path...))

And the implementations of get() and set() are below. Note: checks whether the path is valid is omitted. This implementation uses Type switches:

  1. func get(m interface{}, path ...interface{}) interface{} {
  2. for _, p := range path {
  3. switch idx := p.(type) {
  4. case string:
  5. m = m.(map[string]interface{})[idx]
  6. case int:
  7. m = m.([]interface{})[idx]
  8. }
  9. }
  10. return m
  11. }
  12. func set(v interface{}, m interface{}, path ...interface{}) {
  13. for i, p := range path {
  14. last := i == len(path)-1
  15. switch idx := p.(type) {
  16. case string:
  17. if last {
  18. m.(map[string]interface{})[idx] = v
  19. } else {
  20. m = m.(map[string]interface{})[idx]
  21. }
  22. case int:
  23. if last {
  24. m.([]interface{})[idx] = v
  25. } else {
  26. m = m.([]interface{})[idx]
  27. }
  28. }
  29. }
  30. }

golang depth read map的更多相关文章

  1. 记一次坑爹的golang 二维map判断问题

    记一次坑爹的golang 二维map判断问题 2018年10月18日 23:16:21 yinnnnnnn 阅读数:32更多 个人分类: golang   版权声明:本文为博主原创文章,未经博主允许不 ...

  2. Golang基础教程——map使用篇

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第7篇文章,我们来聊聊golang当中map的用法. map这个数据结构我们经常使用,存储的是key-value的键 ...

  3. Golang,用map写个单词统计器

    Golang中也有实用的泛型编程模板.如map.据Go官方团队称,其实现为Hash表,而非类似cpp或Java的红黑树.所以理论上速度更能快上几个等级(Hash与红黑树的效率对比可以看我的文章C++中 ...

  4. Golang 入门 : 映射(map)

    映射是一种数据结构,用于存储一系列无序的键值对,它基于键来存储值.映射的特点是能够基于键快速检索数据.键就像是数组的索引一样,指向与键关联的值.与 C++.Java 等编程语言不同,在 Golang ...

  5. Golang教程:Map

    什么是 map? Map 是 Go 中的内置类型,它将键与值绑定到一起.可以通过键获取相应的值. 如何创建 map? 可以通过将键和值的类型传递给内置函数 make 来创建一个 map.语法为:mak ...

  6. golang struct 转map 及 map[string]*Struct 初始化和遍历

    package main import ( "encoding/json" "errors" "fmt" "reflect&quo ...

  7. 深入理解golang:sync.map

    疑惑开篇 有了map为什么还要搞个sync.map 呢?它们之间有什么区别? 答:重要的一点是,map并发不是安全的. 在Go 1.6之前, 内置的map类型是部分goroutine安全的,并发的读没 ...

  8. golang struct转map

    struct转map package main import ( "fmt" "reflect" "time" ) type User st ...

  9. golang中,map作为函数参数是如何传递的

    当你声明一个map的时候: m := make(map[int]int) 编译器会调用 runtime.makemap: // makemap implements a Go map creation ...

随机推荐

  1. 分布式 一致性Paxos算法(转载)

    比较通俗易懂,可以入门,转载地址是http://www.cnblogs.com/linbingdong/p/6253479.html Paxos算法在分布式领域具有非常重要的地位.但是Paxos算法有 ...

  2. 使用gpg来加密数据

    一.数据的加密方式 数据加密有三种方式: 1.对称加密(算法有:DES.AES.3DES.)加密和解密使用同一个密钥 2.非对称加密(RSA.DSA.ELGamal等等)一共四把钥匙,用公钥加密数据, ...

  3. pycharm 如何自动添加头注释,比如时间,作者信息等

    查找路径:File->settings->Editor->File and Code Templates->Python Script #!/usr/bin/env pytho ...

  4. maven项目pom.xml中parent标签的使用(转)

    原文地址:https://blog.csdn.net/qq_41254677/article/details/81011681 使用maven是为了更好的帮项目管理包依赖,maven的核心就是pom. ...

  5. 题解 【NOIP2016】魔法阵

    [NOIP2016]魔法阵 Description 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法量. 大魔法师有m个魔法物品,编号分别为1,2,...,m.每个物品具有一个魔法 ...

  6. HTML标签功能分类

    按功能类别对HTML标签进行分类,源自HTML 参考手册 基础 标签 描述 <!DOCTYPE> 定义文档类型. html 定义 HTML 文档. title 定义文档的标题. body ...

  7. $\LaTeX$数学公式大全9

    $9\ Math\ mode\ accents$ $\acute{a}$ \acute{a} $\breve{a}$ \breve{a} $\ddot{a}$ \ddot{a} $\grave{a}$ ...

  8. [题解] [SCOI2010] 生成字符串

    题面 题解 考虑到直接求合法方案不好求, 我们转化为用总方案减去不合法方案 总方案就是\(\binom{n+m}{m}\), 即在\(n+m\)个位置中放\(n\)个数 我们将初始的空序列看做\((0 ...

  9. 面试准备一个访问一个URL的过程简版

    客户端获取URL - > DNS解析 - > TCP连接 - >发送HTTP请求 - >服务器处理请求 - >返回报文 - >浏览器解析渲染页面 - > TC ...

  10. 20165213 Exp9 Web安全基础

    Exp9 Web安全基础 一.基础性问答 (1)SQL注入攻击原理,如何防御 原理:SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序中事先定义好的查询语句的结尾 ...