Golang

无锁编程--atomic.Value

published on
背景 多个goroutine都会读写同一个对象时,必然会有竞争。读写锁或者互斥锁就是解决这种问题的终极方法,但同时性能也是最差的,go在atomic库提供了Value这个类型,实现无锁操作。 实现 type HomeCache map[string]int var homePageInfo atomic.Value func updateHomeCache() error { data := HomeCache{} queryStr := "SELECT source,type,value,wihome FROM wihome_index" rows, _ := adb.DB.Query(queryStr) var source, typ, wihome int var value, key string for rows.Next() { rows.Scan(&source, &typ, &value, &wihome) key = fmt.Sprintf("%d__%d__%s", source, typ, value) data[key] = wihome } if rows.Err() != nil { return rows.Err() } homePageInfo.Store(data) return nil } func GetHomeIdx(source int, did string, mid int, node string) (idx int) { data := homePageInfo. Read More...

无锁编程--优先级channel

published on
背景 处理channel中的数据过程中,涉及到配置的变更,配置变更后,数据的处理方式会跟随改变。在配置可以热加载的应用中,如何更新配置结构并应用新配置,而不产生竞争。 实现 方法有很多,锁、原子操作、atomic.Value等,但都不是这里的方法。按照golang的哲学,实现如下: func filter(srcC <-chan *T) <-chan *T { c := make(chan *T, 1024) conf := GetConfig() var dataP *T go func() { for { select { //select + default 实现优先级channel case <-eventC: conf = GetConfig() default: dataP = <-srcC if _, ok := conf[dataP.Id]; ok { c <- dataP } } } }() return c }

闭包--事务化插入数据

published on
背景 将队列中的数据持久化到数据库中时,不能每来一条数据就一次数据插入,肯定要批量插入。 实现 import "database/sql" func beTransaction(db *sql.DB, stmtStr string, n int) (func(...interface{}) error, func() error) { i := 1 tx, _ := db.Begin() txstmt, _ := tx.Prepare(stmtStr) return func(args ...interface{}) error { var err error _, err = txstmt.Exec(args...) if err != nil { return err } i++ if i > n { err = tx.Commit() if err != nil { return err } i = 1 tx, _ = db. Read More...