遍历一个月的每一天

inDay := "2019-05-03"
m, _ := time.Parse("2006-1-2", inDay)

// 如果传入的日子不是第一天,需求从第一天开始, 做一个处理
if m.Day() > 0 {
	m = m.AddDate(0, 0, -m.Day()+1)
}

for d := m; d.Month() == m.Month(); d = d.AddDate(0, 0, 1) {
	log.Println(d.Day())
}
	
// 2019/05/14 16:32:02 1
// 2019/05/14 16:32:02 2
// 2019/05/14 16:32:02 ...
// 2019/05/14 16:32:02 4

golang map 并发读写问题

blog.golang.org

package main

import "sync"

type SafeMap struct {
    sync.RWMutex
    Map map[int]int
}

func main() {
    safeMap := newSafeMap(10)

    for i := 0; i < 100000; i++ {
        go safeMap.writeMap(i, i)
        go safeMap.readMap(i)
    }

}

func newSafeMap(size int) *SafeMap {
    sm := new(SafeMap)
    sm.Map = make(map[int]int)
    return sm

}

func (sm *SafeMap) readMap(key int) int {
    sm.RLock()
    value := sm.Map[key]
    sm.RUnlock()
    return value
}

func (sm *SafeMap) writeMap(key int, value int) {
    sm.Lock()
    sm.Map[key] = value
    sm.Unlock()
}

字符字数

// GetStrLength 返回输入的字符串的字数,汉字和中文标点算 1 个字数,英文和其他字符 2 个算 1 个字数,不足 1 个算 1个

func GetStrLength(str string) float64 {
	var total float64
 
	reg := regexp.MustCompile("/·|,|。|《|》|‘|’|”|“|;|:|【|】|?|(|)|、/")
 
	for _, r := range str {
		if unicode.Is(unicode.Scripts["Han"], r) || reg.Match([]byte(string(r))) {
			total = total + 1
		} else {
			total = total + 0.5
		}
	}
 
	return math.Ceil(total)
}

需求

在 mac 机器上, 终端用的比较频繁

如: 命令行下用sublime、vscode、atom打开文件或目录 如: 当前文件夹打开命令行

当前文件夹打开命令行

正常操作是在文件的右键-服务-打开iterm, 步骤比较多

可以安装一个 Go2shell 的工具

安装过程有一点, 需要在 application 文件夹,按 command 键拖动 Go2shellFinder bar 上面…

激活码 DONATE_BY_FOLLOW

命令行下用sublime、vscode、atom打开文件或目录

如何找路径, 右键查看包内容, 找到执行文件

alias atom='/Applications/Atom.app/Contents/MacOS/Atom'
alias subl='/Applications/SublimeText.app/Contents/SharedSupport/bin/subl'
alias code='/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code'

vscode 额外:

对于Mac用户,我们需要通过设置使您能够从终端内启动VS Code.首选运行VS code并打开命令面板( ⇧⌘P ),然后输入 shell command 找到: Install ‘code’ command in PATH 。

# 有时你想打开或者创建一个文件。如果指定文件不存在,VS Code将会为你创建此文件。
# 你可以通过空格键来分隔许多文件名
code index.html style.css readme.md
code 
-h code使用说明
-v 版本
-n new
-g 跳转行
-d 对比,打开一个不同的编辑器。需要两个文件路径作为参数。例如:code -d file file


如何不用 redis 设计一个排行榜

在通用排行榜采用 redis 的 sorted set 作为解决方案已经是通用方案了

但业务需求并不是单一需求, 比如玩家最近一关的破解时间来排定, 既鼓励准确率, 又鼓励速度. 换句话说, coin(金币)为第一排序因素, time(破解时间)为第二排序因素.

而 redis 的 sorted set 是单一维度, 只有一个 score 如何解决两个维度的数据排行呢?

很多常规思路是把多维转成一维, 然后将数据存入 score

另外一种思路是将两个因素并入一个因素, 很幸运 coin + time 可以并成一个 score 从而免除一些逻辑计算

当然这篇文章并不是介绍 redis 的

buntdb

BuntDB is an embeddable, in-memory key/value database for Go with custom indexing and geospatial support

直接上代码, 看下BuntDB解决方案, 天生支持多维索引, 厉害了

db, _ := buntdb.Open(":memory:")
db.CreateIndex("last_name_age", "*", buntdb.IndexJSON("name.last"), buntdb.IndexJSON("age"))
db.Update(func(tx *buntdb.Tx) error {
	tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil)
	tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil)
	tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil)
	tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil)
	tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil)
	tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil)
	return nil
})
db.View(func(tx *buntdb.Tx) error {
	tx.Ascend("last_name_age", func(key, value string) bool {
		fmt.Printf("%s: %s\n", key, value)
		return true
	})
	return nil
})

// Output:
// 5: {"name":{"first":"Sam","last":"Anderson"},"age":51}
// 3: {"name":{"first":"Carol","last":"Anderson"},"age":52}
// 4: {"name":{"first":"Alan","last":"Cooper"},"age":28}
// 1: {"name":{"first":"Tom","last":"Johnson"},"age":38}
// 6: {"name":{"first":"Melinda","last":"Prichard"},"age":44}
// 2: {"name":{"first":"Janet","last":"Prichard"},"age":47}

排行榜数据多, 几个维度都没有问题, 值得注意的是排序字段, 如果是数字型, json 里面必须也是数字型, 字符型的数字排序会有问题