Go 语言是静态类型语言,虽然它也可以表现出动态类型,但是使用一个嵌套的 map[string]interface{} 在那里乱叫会让代码变得特别丑。通过掌握语言的静态特性,我们可以做的更好。
通过同一通道交换多种信息的时候,我们经常需要 JSON 具有动态的,或者更合适的参数内容。首先,让我们来讨论一下消息封装(message envelopes),JSON 在这里看起来就像这样:
通过 interface{},我们可以很容易的将数据结构编码成为独立封装的,具有多种类型的消息体的 JSON 数据。为了生成下面的 JSON :
我们可以使用这些 Go 类型:
输出的结果是:
这些并没有什么特殊的。
如果你想将上面的 JSON 对象解析成为一个 Envelope 类型的对象,最终你会将 Msg 字段解析成为一个 map[string]interface{}。 这种方式不是很好用,会使你后悔你的选择。
输出:
就像前面说的,我推荐修改 Envelope 类型,就像这样:
json.RawMessage 非常有用,它可以让你延迟解析相应的 JSON 数据。它会将未处理的数据存储为 []byte。
这种方式可以让你显式控制 Msg 的解析。从而延迟到获取到 Type 的值之后,依据 Type 的值进行解析。这种方式不好的地方在于你需要先明确解析 Msg,或者你需要单独分为 EnvelopeIn 和 EnvelopeOut 两种类型,其中 EnvelopeOut 仍然有 Msg interface{}。
那么如何将上述两者好的一面结合起来呢?通过在 interface{} 字段中放入 *json.RawMessage!
输出:
虽然我极其推荐你将动态可变的部分放在一个单独的 key 下面,但是有时你可能需要处理一些预先存在的数据,它们并没有用这样的方式进行格式化。
如果可以的话,请使用文章前面提到的风格。
我们可以通过解析两次数据的方式来解决。
dynamite
前面,我们讲了map的用法以及原理 Golang中map的实现原理 ,但我们知道,map在并发读写的情况下是不安全。需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,今天,我们就来讲讲 sync.Map的用法以及原理
sync.Map与map不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构:
我们下来看下sync.Map结构体
结构体之间的关系如下图所示:
总结一下:
Load方法比较简单,总结一下:
总结如下:
Map是java中的接口,Map.Entry是Map的一个内部接口。
Map提供了一些常用方法,如keySet()、entrySet()等方法,keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。
Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
由以上可以得出,遍历Map的常用方法:
1.
Map map = new HashMap()Irerator iterator = map.entrySet().iterator()
while(iterator.hasNext()) {
Map.Entry entry = iterator.next()
Object key = entry.getKey()
//
}
2.
Map map = new HashMap()Set keySet= map.keySet()
Irerator iterator = keySet.iterator
while(iterator.hasNext()) {
Object key = iterator.next()
Object value = map.get(key)
//
}
另外,还有一种遍历方法是,单纯的遍历value值,Map有一个values方法,返回的是value的Collection集合。通过遍历collection也可以遍历value,如
Map map = new HashMap()Collection c = map.values()
Iterator iterator = c.iterator()
while(iterator.hasNext()) {
Object value = iterator.next()
}
/*---------------------------详解2----------------------------------*/
你是否已经对每次从Map中取得关键字然后再取得相应的值感觉厌倦?使用Map.Entry类,你可以得到在同一时间得到所有的信息。标准的Map访问方法如下:
Set keys = map.keySet( )if(keys != null) {
Iterator iterator = keys.iterator( )
while(iterator.hasNext( )) {
Object key = iterator.next( )
Object value = map.get(key)
....
}
}
然后,这个方法有一个问题。从Map中取得关键字之后,我们必须每次重复返回到Map中取得相对的值,这是很繁琐和费时的。
幸运的是,这里有一个更加简单的途径。Map类提供了一个称为entrySet()的方法,这个方法返回一个Map.Entry实例化后的对象集。 接着,Map.Entry类提供了一个getKey()方法和一个getValue()方法,因此,上面的代码可以被组织得更符合逻辑。举例如下:
Set entries = map.entrySet( )if(entries != null) {
Iterator iterator = entries.iterator( )
while(iterator.hasNext( )) {
Map.Entry entry =iterator.next( )
Object key = entry.getKey( )
Object value = entry.getValue()
....
}
}
尽管增加了一行代码,我们却省略了许多对Map不必要的“get”调用。同时,提供给开发人员一个同时保持了关键字和其对应的值的类。Map.Entry同时也提供了一个setValue()方法,程序员可以使用它修改map里面的值。