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: }
db.Preload("Users", func(db *gorm.DB) *gorm.DB { return db.Order("user.age DESC") }).Find(&users) // SELECT * FROM user WHERE id IN (1,2,3,4) order by user.age DESC;
2.
order by
常用 指定从数据库检索记录时的排序方式
1 2 3 4 5 6 7 8 9 10 11
db.Order("age desc, name").Find(&users) // SELECT * FROM users ORDER BY age desc, name;
// 多个 order db.Order("age desc").Order("name").Find(&users) // SELECT * FROM users ORDER BY age desc, name;
db.Clauses(clause.OrderBy{ Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true}, }).Find(&User{}) // SELECT * FROM users ORDER BY FIELD(id,1,2,3)
order by field 自定义排序 使用上面的写法通过自定义字段排序时注意,WithoutParentheses为true,为false是构建的sql为order by field(column,(“f1,f2,f3,…”)),会报错
db.Clauses(hints.UseIndex("idx_user_name")).Find(&User{}) // SELECT * FROM `users` USE INDEX (`idx_user_name`)
db.Clauses(hints.ForceIndex("idx_user_name", "idx_user_id").ForJoin ()).Find(&User{}) // SELECT * FROM `users` FORCE INDEX FOR JOIN (`idx_user_name`, `idx_user_id`)"
Index 用于提高数据检索和 SQL 查询性能。 Index Hints 向优化器提供了在查询处理过程中如何选择索引的信息。与 optimizer 相比,它可以更灵活地选择更有效的执行计划
加了join
1 2 3 4
db.Table("`order` FORCE INDEX (order_create_time_d977ab1e,idx_demand_number, idx_stocked_number,idx_di)"). //Clauses(hints.CommentBefore("from", "FORCE INDEX (order_create_time_d977ab1e, idx_demand_number,idx_stocked_number,idx_di)")). // 这样写,生成的sql语句有问题,force index位置在where条件中间 Joins("left join servicelist on order.service_list_id=servicelist.id").Find(& orders)
Delete
Config
ConnPool
gorm 连接池配置通过sql.DB实现
1 2 3 4 5 6 7 8 9
gormDB,err:=gorm.Open(...) db,err:=gormDB.DB() if err!=nil{ return } db.SetConnMaxLifetime() //连接最长复用时间 db.SetConnMaxIdleTime() //maximum amount of time a connection may be idle,最长空闲时间 db.SetMaxIdleConns() // 最长空闲时间 maximum number of connections in the idle connection pool db.SetMaxOpenConns() // 最大连接数 maximum number of open connections to the database