redis底层存储使用的不是简单的链表,使用了quicklist(快速链表:A doubly linked list of ziplists意思为一个由ziplist组成的双向链表)。 ziplist,压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会 改成 quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间,而且会加重内存的碎片化。
set
Usage
api
redis support sadd,members…
1 2 3 4 5 6 7 8 9 10 11 12 13
// using go-zero gofunc() { for { s := time.Now().Second() redis.Sadd("order_id"+strconv.Itoa(s), strconv.Itoa(s)) } }() tt := time.NewTicker(time.Second) for now := range tt.C { vs, _ := rr.Smembers("order_id" + strconv.Itoa(now.Second() )) fmt.Println(now.Second(), vs) redis.Del("order_id" + strconv.Itoa(now.Second())) }
type Sequence []int func(s Sequence)Sort()[]int{ copy:=make(Sequence,0,len(s)) append(copy,s...) sort.IntSlice(s).Sort() }
断言防止panic,使用安全方式
1 2 3 4 5 6 7 8 9 10
var list interface{} list=&Sequence{1,2,4,3} // 不安全方式,assertion不成功,会panic convert:=list.(*Sequence)
// 安全方式 convert,ok:=list.(*Sequence) if !ok{ return errors.New("convert error") }
反射,通过CanSet()判断反射得到的值能否修改
1 2 3
var f float64=3 val:=reflect.ValueOf(x) val.CanSet()
反射在标准库中大量使用,fmt.Fprintf及其他格式化函数大多使用反射实现;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//fmt.Fprintf funcFprintf(w io.Writer, format string, a ...interface{})(n int, err error) { p := newPrinter() p.doPrintf(format, a) n, err = w.Write(p.buf) p.free() return }
// 判断interface的类型,在go 1.15 ".(type)"只能在switch使用 var i interface{}=&os.File{} switch val.(type){ caseint: case *os.File: casestring: }