Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
package dfaUtil
|
||||
|
||||
import "strings"
|
||||
|
||||
/*
|
||||
DFA util, is used to verify whether a sentence has invalid words.
|
||||
The underlying data structure is trie.
|
||||
https://en.wikipedia.org/wiki/Trie
|
||||
*/
|
||||
|
||||
// dfa util
|
||||
type DFAUtil struct {
|
||||
// The root node
|
||||
root *trieNode
|
||||
}
|
||||
|
||||
// 搜索语句
|
||||
// 由于go不支持tuple,所以为了避免定义多余的struct,特别使用两个list来分别返回匹配的索引的上界和下界
|
||||
// 在处理此方法的返回值时,需要两者配合使用
|
||||
// 参数:
|
||||
//
|
||||
// sentence:语句字符串
|
||||
//
|
||||
// 返回:
|
||||
//
|
||||
// 搜索到的开始位置列表
|
||||
// 搜索到的结束位置列表
|
||||
func (this *DFAUtil) SearchSentence(sentence string) (startIndexList, endIndexList []int) {
|
||||
sentenceRuneList := []rune(sentence)
|
||||
for i := 0; i < len(sentenceRuneList); {
|
||||
//按序匹配每个字
|
||||
end := this.searchSentenceByStart(i, sentenceRuneList)
|
||||
if end < 0 {
|
||||
//匹配失败,继续匹配下一个字
|
||||
i++
|
||||
} else {
|
||||
//匹配成功,记录索引位置
|
||||
startIndexList = append(startIndexList, i)
|
||||
endIndexList = append(endIndexList, end)
|
||||
|
||||
//从匹配到的字后面开始找
|
||||
i = end + 1
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 从指定的开始位置搜索语句
|
||||
// 参数:
|
||||
//
|
||||
// start:开始匹配的位置
|
||||
// sentenceRuneList:语句字列表
|
||||
//
|
||||
// 返回:
|
||||
//
|
||||
// 匹配到的结束位置,未匹配到返回-1
|
||||
func (this *DFAUtil) searchSentenceByStart(start int, sentenceRuneList []rune) (endIndex int) {
|
||||
//当前节点,从根节点开始找
|
||||
currNode := this.root
|
||||
//是否匹配到
|
||||
var isMatched bool
|
||||
|
||||
//按顺序匹配字
|
||||
for i := start; i < len(sentenceRuneList); {
|
||||
child, exists := currNode.children[sentenceRuneList[i]]
|
||||
|
||||
//未匹配到则结束,跳出循环(可能匹配到过词结尾)
|
||||
if !exists {
|
||||
break
|
||||
}
|
||||
|
||||
//是否是词末尾,如果是则先记录下来,因为还可能匹配到更长的词
|
||||
//比如["金鳞"、"金鳞岂是池中物"] => 匹配"金鳞岂是池中物",匹配到"金鳞"不应该停下来,应继续匹配更长的词
|
||||
if child.isEndOfWord {
|
||||
endIndex = i
|
||||
isMatched = true
|
||||
}
|
||||
|
||||
//是否已经到词末尾
|
||||
if len(child.children) == 0 {
|
||||
return endIndex
|
||||
} else {
|
||||
//继续与后面的字匹配
|
||||
currNode = child
|
||||
}
|
||||
|
||||
//增加索引匹配下一个位置
|
||||
i++
|
||||
}
|
||||
|
||||
//匹配结束,若曾经匹配到词末尾,则直接返回匹配到的位置
|
||||
if isMatched {
|
||||
return endIndex
|
||||
} else {
|
||||
//没有匹配到词末尾,则返回匹配失败
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// Insert new word into object
|
||||
func (this *DFAUtil) InsertWord(word []rune) {
|
||||
currNode := this.root
|
||||
for _, c := range word {
|
||||
if cildNode, exist := currNode.children[c]; !exist {
|
||||
cildNode = newtrieNode()
|
||||
currNode.children[c] = cildNode
|
||||
currNode = cildNode
|
||||
} else {
|
||||
currNode = cildNode
|
||||
}
|
||||
}
|
||||
|
||||
currNode.isEndOfWord = true
|
||||
}
|
||||
|
||||
// Check if there is any word in the trie that starts with the given prefix.
|
||||
func (this *DFAUtil) StartsWith(prefix []rune) bool {
|
||||
currNode := this.root
|
||||
for _, c := range prefix {
|
||||
if childNode, exist := currNode.children[c]; !exist {
|
||||
return false
|
||||
} else {
|
||||
currNode = childNode
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Judge if input sentence contains some special caracter
|
||||
// Return:
|
||||
// Matc or not
|
||||
func (this *DFAUtil) IsMatch(sentence string) bool {
|
||||
startIndexList, _ := this.SearchSentence(sentence)
|
||||
return len(startIndexList) > 0
|
||||
}
|
||||
|
||||
// Handle sentence. Use specified caracter to replace those sensitive caracters.
|
||||
// input: Input sentence
|
||||
// replaceCh: candidate
|
||||
// Return:
|
||||
// Sentence after manipulation
|
||||
func (this *DFAUtil) HandleWord(sentence string, replaceCh rune) string {
|
||||
startIndexList, endIndexList := this.SearchSentence(sentence)
|
||||
if len(startIndexList) == 0 {
|
||||
return sentence
|
||||
}
|
||||
|
||||
// Manipulate
|
||||
sentenceList := []rune(sentence)
|
||||
for i := 0; i < len(startIndexList); i++ {
|
||||
for index := startIndexList[i]; index <= endIndexList[i]; index++ {
|
||||
sentenceList[index] = replaceCh
|
||||
}
|
||||
}
|
||||
|
||||
return string(sentenceList)
|
||||
}
|
||||
|
||||
// Handle sentence. Use specified caracter to replace those sensitive caracters.
|
||||
// input: Input sentence
|
||||
// replaceCh: candidate
|
||||
// Return:
|
||||
// Sentence after manipulation
|
||||
func (this *DFAUtil) HandleWordUseStr(input string, replaceCh string) string {
|
||||
input2 := strings.ToUpper(input)
|
||||
|
||||
startIndexList, endIndexList := this.SearchSentence(input2)
|
||||
if len(startIndexList) == 0 {
|
||||
return input
|
||||
}
|
||||
|
||||
// Manipulate
|
||||
inputRune := []rune(input)
|
||||
replaceChList := []rune(replaceCh)
|
||||
|
||||
//上一次替换掉的数量
|
||||
lastReplaceCount := 0
|
||||
|
||||
for i := 0; i < len(startIndexList); i++ {
|
||||
|
||||
//替换字的索引
|
||||
index := len(replaceChList)
|
||||
|
||||
//开始位置--加上替换的词的索引
|
||||
starIndex := startIndexList[i] + (i * index) - lastReplaceCount
|
||||
|
||||
//结束位置
|
||||
endIndex := endIndexList[i] + (i * index) - lastReplaceCount
|
||||
|
||||
//结束字符串
|
||||
sentenceAttr := string(inputRune[endIndex+1:])
|
||||
|
||||
//替换范围字符串
|
||||
inputRune = append(inputRune[:starIndex], replaceChList...)
|
||||
inputRune = append(inputRune, []rune(sentenceAttr)...)
|
||||
lastReplaceCount = endIndex + 1 - starIndex
|
||||
}
|
||||
|
||||
return string(inputRune)
|
||||
}
|
||||
|
||||
// Create new DfaUtil object
|
||||
// wordList:word list
|
||||
func NewDFAUtil(wordList []string) *DFAUtil {
|
||||
this := &DFAUtil{
|
||||
root: newtrieNode(),
|
||||
}
|
||||
|
||||
for _, word := range wordList {
|
||||
wordRuneList := []rune(word)
|
||||
if len(wordRuneList) > 0 {
|
||||
this.InsertWord(wordRuneList)
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# 配置根节点
|
||||
root:
|
||||
# 是否是调试模式
|
||||
debug: true
|
||||
|
||||
# Web服务监听地址和端口
|
||||
web_server_address: "192.168.50.85:10052"
|
||||
|
||||
# Elasticsearch 地址
|
||||
es_urls: "http://10.252.0.70:18099"
|
||||
|
||||
# 数据库配置
|
||||
db_config:
|
||||
admin_db:
|
||||
# 最大处于开启状态的连接数
|
||||
max_open_conns: 0
|
||||
|
||||
# 最大处于空闲状态的连接数
|
||||
max_idle_conns: 0
|
||||
|
||||
# 数据库连接字符串
|
||||
connection_string: "root:Qq5201530300@tcp(192.168.50.110:3306)/admin?charset=utf8&parseTime=true&loc=Local&timeout=30s&multiStatements=true"
|
||||
|
||||
user_db:
|
||||
# 最大处于开启状态的连接数
|
||||
max_open_conns: 0
|
||||
|
||||
# 最大处于空闲状态的连接数
|
||||
max_idle_conns: 0
|
||||
|
||||
# 数据库连接字符串
|
||||
connection_string: "root:Qq5201530300@tcp(192.168.50.110:3306)/user?charset=utf8&parseTime=true&loc=Local&timeout=30s&multiStatements=true"
|
||||
|
||||
redis_config:
|
||||
# 数据库连接字符串
|
||||
connection_string: "192.168.50.110:6379"
|
||||
|
||||
# 密码, 如果要设置用户Id,则密码设置为:"UserId:Password"
|
||||
password: ""
|
||||
|
||||
# 数据库序号
|
||||
database: 5
|
||||
|
||||
# 最大活跃连接数
|
||||
max_active: 500
|
||||
|
||||
# 最大空闲的连接数
|
||||
max_idle: 200
|
||||
|
||||
# 连接空闲超时时间,单位:秒
|
||||
idle_timeout: 300
|
||||
|
||||
# 连接超时时间, 单位:秒
|
||||
dial_connect_timeout: 10
|
||||
@@ -0,0 +1,123 @@
|
||||
package redisUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Redis配置对象
|
||||
type RedisConfig struct {
|
||||
// 连接字符串
|
||||
ConnectionString string
|
||||
|
||||
// 密码
|
||||
Password string
|
||||
|
||||
// 数据库编号
|
||||
Database int
|
||||
|
||||
// 最大活跃连接数
|
||||
MaxActive int
|
||||
|
||||
// 最大空闲连接数
|
||||
MaxIdle int
|
||||
|
||||
// 空闲超时
|
||||
IdleTimeout time.Duration
|
||||
|
||||
// 连接超时
|
||||
DialConnectTimeout time.Duration
|
||||
}
|
||||
|
||||
// 将redis连接字符串转化为redis config对象
|
||||
// 格式:ConnectionString=10.1.0.21:6379;Password=redis_pwd;Database=3;MaxActive=50;MaxIdle=20;IdleTimeout=300;DialConnectTimeout=10;
|
||||
// redisConfigStr:redis连接字符串
|
||||
// 返回值:
|
||||
// redis config对象
|
||||
// 错误对象
|
||||
func NewRedisConfig(redisConfigStr string) (redisConfig *RedisConfig, err error) {
|
||||
var connectionString string
|
||||
var password string
|
||||
var database int
|
||||
var maxActive int
|
||||
var maxIdle int
|
||||
var idleTimeout time.Duration
|
||||
var dialConectTimeout time.Duration
|
||||
var count int = 7
|
||||
var subCount int = 2
|
||||
|
||||
itemList := strings.Split(redisConfigStr, ";")
|
||||
// 去掉最后的空数据
|
||||
if itemList[len(itemList)-1] == "" {
|
||||
itemList = itemList[0 : len(itemList)-1]
|
||||
}
|
||||
if len(itemList) != count {
|
||||
err = fmt.Errorf("%s格式不正确,需要包含%d个部分,现在有%d个部分", redisConfigStr, count, len(itemList))
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range itemList {
|
||||
subItemList := strings.Split(item, "=")
|
||||
if len(subItemList) != subCount {
|
||||
err = fmt.Errorf("%s格式不正确,需要包含%d个部分", item, subCount)
|
||||
return
|
||||
}
|
||||
|
||||
// 分别进行判断
|
||||
switch strings.ToLower(subItemList[0]) {
|
||||
case strings.ToLower("ConnectionString"):
|
||||
connectionString = subItemList[1]
|
||||
case strings.ToLower("Password"):
|
||||
password = subItemList[1]
|
||||
case strings.ToLower("Database"):
|
||||
if database, err = strconv.Atoi(subItemList[1]); err != nil {
|
||||
err = fmt.Errorf("%s转化为int型失败", subItemList[1])
|
||||
return
|
||||
}
|
||||
case strings.ToLower("MaxActive"):
|
||||
if maxActive, err = strconv.Atoi(subItemList[1]); err != nil {
|
||||
err = fmt.Errorf("%s转化为int型失败", subItemList[1])
|
||||
return
|
||||
}
|
||||
case strings.ToLower("MaxIdle"):
|
||||
if maxIdle, err = strconv.Atoi(subItemList[1]); err != nil {
|
||||
err = fmt.Errorf("%s转化为int型失败", subItemList[1])
|
||||
return
|
||||
}
|
||||
case strings.ToLower("IdleTimeout"):
|
||||
if idleTimeout_int, err1 := strconv.Atoi(subItemList[1]); err1 != nil {
|
||||
err = fmt.Errorf("%s转化为int型失败", subItemList[1])
|
||||
return
|
||||
} else {
|
||||
idleTimeout = time.Duration(idleTimeout_int) * time.Second
|
||||
}
|
||||
case strings.ToLower("DialConnectTimeout"):
|
||||
if dialConectTimeout_int, err1 := strconv.Atoi(subItemList[1]); err1 != nil {
|
||||
err = fmt.Errorf("%s转化为int型失败", subItemList[1])
|
||||
return
|
||||
} else {
|
||||
dialConectTimeout = time.Duration(dialConectTimeout_int) * time.Second
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
redisConfig = NewRedisConfig2(connectionString, password, database, maxActive, maxIdle, idleTimeout, dialConectTimeout)
|
||||
return
|
||||
}
|
||||
|
||||
func NewRedisConfig2(connectionString, password string,
|
||||
database, maxActive, maxIdle int,
|
||||
idleTimeout, dialConnectTimeout time.Duration) *RedisConfig {
|
||||
|
||||
return &RedisConfig{
|
||||
ConnectionString: connectionString,
|
||||
Password: password,
|
||||
Database: database,
|
||||
MaxActive: maxActive,
|
||||
MaxIdle: maxIdle,
|
||||
IdleTimeout: idleTimeout,
|
||||
DialConnectTimeout: dialConnectTimeout,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user