2017-02-17
Go1.8发布了,这里先简单学习一下Go1.8的几个新特性。
新的切片排序Api
#
在以前要对切片排序要实现sort.Interface接口:
1package main
2
3import (
4 "fmt"
5 "sort"
6)
7
8type Person struct {
9 Name string
10 Age int
11}
12
13func (p Person) String() string {
14 return fmt.Sprintf("%s: %d", p.Name, p.Age)
15}
16
17// ByAge implements sort.Interface for []Person based on
18// the Age field.
19type ByAge []Person
20
21func (a ByAge) Len() int { return len(a) }
22func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
23func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
24
25func main() {
26 people := []Person{
27 {"Bob", 31},
28 {"John", 42},
29 {"Michael", 17},
30 {"Jenny", 26},
31 }
32
33 fmt.Println(people)
34 sort.Sort(ByAge(people))
35 fmt.Println(people)
36
37}
现在只需这样做:
...2017-01-22
JSON作为一种在不同平台间的数据交换格式,Go的标准包encoding/json中实现了对json的编码(marshal)和解码(unmarshal)功能。
json.Marshal
#
json.Marshal函数实现Json的编码:
- 如果给定的值不等于nil并且实现了json.Marshaler接口,调用json.Marshaler的MarshalJSON方法完成编码
- 如果没有实现json.Marshaler接口,而是实现了encoding.TextMarshaler,将调用其MarshalText完成编码
- 否则将按照下面的默认情况进行编码:
- bool 编码为 JSON boolean
- 整形,浮点型等数值 编码为 JSON number
- string 编码为 JSON string
- array和slice编码为JSON array, []byte作为例外会被编码成base64 string
- map[string]interface{}编码为JSON object
- struct编码为JSON object(只适用struct的可导出字段)
- nil编码为JSON null
json tag定制struct编码
#
2016-12-20
从Go 1.7 runtime包理解Golang GC
#
Go也是垃圾回收的,实现方式和别的语言不太一样。
先从Go的标准库的runtime包说起,这个包有很多运行时相关的类型和函数。
调用runtimea.GC()可以触发GC,但我们一般不会这么做,先读一下这个函数的注释说明。
1GC runs a garbage collection and blocks the caller until the garbage collection is complete.
2It may also block the entire program
大概的意思是,Go的GC触发时会阻塞整个程序的运行。这个在垃圾回收里面有一个比较有名的名词叫STW,Stop the World。就是说程序在GC时“整个世界会停止下来”。
Go垃圾回收的STW一直是Go语言被指责和诟病最多的地方,也是Go的每个版本都努力改进的地方。
...2016-11-15
map的内部结构
#
Go中的map使用哈希表实现的,在源码go runtime/hashmap.go中可以看到对应实现。
1// A header for a Go map.
2type hmap struct {
3 // Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and
4 // ../reflect/type.go. Don't change this structure without also changing that code!
5 count int // # live cells == size of map. Must be first (used by len() builtin)
6 flags uint8
7 B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
8 noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
9 hash0 uint32 // hash seed
10
11 buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
12 oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
13 nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
14
15 // If both key and value do not contain pointers and are inline, then we mark bucket
16 // type as containing no pointers. This avoids scanning such maps.
17 // However, bmap.overflow is a pointer. In order to keep overflow buckets
18 // alive, we store pointers to all overflow buckets in hmap.overflow.
19 // Overflow is used only if key and value do not contain pointers.
20 // overflow[0] contains overflow buckets for hmap.buckets.
21 // overflow[1] contains overflow buckets for hmap.oldbuckets.
22 // The first indirection allows us to reduce static size of hmap.
23 // The second indirection allows to store a pointer to the slice in hiter.
24 overflow *[2]*[]*bmap
25}
26
27// A bucket for a Go map.
28type bmap struct {
29 // tophash generally contains the top byte of the hash value
30 // for each key in this bucket. If tophash[0] < minTopHash,
31 // tophash[0] is a bucket evacuation state instead.
32 tophash [bucketCnt]uint8
33 // Followed by bucketCnt keys and then bucketCnt values.
34 // NOTE: packing all the keys together and then all the values together makes the
35 // code a bit more complicated than alternating key/value/key/value/... but it allows
36 // us to eliminate padding which would be needed for, e.g., map[int64]int8.
37 // Followed by an overflow pointer.
38}
先删掉代码原有注释,以便于查看:
...2016-11-15
slice的内部结构
#
一个slice本质上是一个数组的某个部分的引用。在go runtime/slice.go源码中定义了slice的结构:
1type slice struct {
2 array unsafe.Pointer
3 len int
4 cap int
5}
可以看到在Go的内部,slice是一个包含3个字段的结构体:
...2016-03-01
1. encoding/binary包简介
#
在用Go进行数据传输的场景下,例如文件传输或文件存储时,需要将Go的数据例如int转换为[]byte。
得到的[]byte
可以进一步在网络上传输或写入到文件中。这个场景需要借助go标准库中的encoding/binary
包来实现。
encoding/binary
包实现了简单的数字与字节序列的转换以及变长值的编解码。
一个定长值是指要么是固定长度的数字类型(int8, uint8, int16, float32, complex64, …)或者只包含定长值的结构体或者数组。
...2015-02-03
sync.Pool可以被看做是存放可被重用的值的容器,这个容器具有以下特性:可自动伸缩、高效、并发安全。
因为它的使用场景并不适用于诸如数据库连接池
这类需要我们自己管理生命周期的资源对象的池化场景,所以一般把sync.Pool
称为临时对象池(其实叫做临时对象缓存更合适),主要用来存放已经分配的但是暂时不需要使用的对象,在需要使用的时候再从临时对象池中取出。
...2015-01-05
CSP(CommunicatingSequentialProcess)中文翻译"通信顺序进程"或"交换信息的循序进程", CSP描述了一种并发系统进行交互的模式。
CSP允许使用进程组件来描述系统,这些进程组件独立运行并且通过消息传递的方式通信。
...