欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Go語言實現(xiàn)敏感詞過濾功能

 更新時間:2023年12月18日 08:26:14   作者:郭強112  
敏感詞過濾,算是一個比較常見的功能,尤其是在內(nèi)容、社交類應(yīng)用中更是如此,本文介紹如何使用Go語言實現(xiàn)簡單的敏感詞過濾功能,文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下

簡單敏感詞過濾-ai版

先列出一個gpt給出來的一個簡單前綴樹的實現(xiàn):

// 初始化敏感詞切片
var sensitiveWords = []string{}

// TrieNode 表示Trie樹的節(jié)點
type TrieNode struct {
	children map[rune]*TrieNode
	isEnd    bool
	Text     string
}

// Trie 表示敏感詞的Trie樹
type Trie struct {
	root *TrieNode
}

// NewTrie 創(chuàng)建一個新的Trie樹
func NewTrie() *Trie {
	return &Trie{
		root: &TrieNode{
			children: make(map[rune]*TrieNode),
			isEnd:    false,
		},
	}
}

// Insert 將一個敏感詞插入到Trie樹中
func (t *Trie) Insert(word string) {
	node := t.root
	for _, char := range []rune(word) {
		if _, ok := node.children[char]; !ok {
			node.children[char] = &TrieNode{
				children: make(map[rune]*TrieNode),
				isEnd:    false,
			}
		}
		node = node.children[char]
	}

	node.Text = word
	node.isEnd = true
}

// Contains 檢測文本中是否包含敏感詞
func (t *Trie) Contains(text string) bool {
	node := t.root
	for _, char := range []rune(text) {
		if _, ok := node.children[char]; !ok {
			continue
		}
		node = node.children[char]
		if node.isEnd {
			return true
		}
	}
	return false
}

這個版本的代碼中,構(gòu)建了一個簡單的前綴樹來存儲敏感詞,如果某個節(jié)點存儲的是敏感詞的最后一個字符,則isEnd值為true。這樣,當(dāng)我們檢測到某個節(jié)點的isEnd值為true時,就說明檢測到了敏感詞。

如果只是為了檢測到一段文本是否包含敏感詞,而不需要匹配出所有的敏感詞,那實際上在敏感詞a包含敏感詞b時,我們可以只存儲單詞b。

我們編寫一個測試用例,測試一下上面的代碼:

func TestCheckWord1(t *testing.T) {
	trie := NewTrie()
	for _, word := range sensitiveWords {
		trie.Insert(word)
	}

	content := "這里是一段非法活動文本。"

	search := trie.Contains(content)

	assert.Equal(t, search, true)
}

測試結(jié)果如下:

測試通過。(再這樣下去程序員真要失業(yè)了?。?/p>

當(dāng)然,上面的代碼不完善,例如:不是并發(fā)安全的、不支持刪除敏感詞、沒有返回檢測到的敏感詞。我們來完善一下。

完善敏感詞過濾

下面我們在上面的代碼基礎(chǔ)上,添加一些功能。

package sensitivewordcheck

import "sync"

// TrieV1Node 表示TrieV1樹的節(jié)點
type TrieV1Node struct {
	children map[rune]*TrieV1Node // 子節(jié)點
	isEnd    bool
	Text     string
	Value    rune
	parent   *TrieV1Node // 父節(jié)點
}

// TrieV1 表示敏感詞的TrieV1樹
type TrieV1 struct {
	root *TrieV1Node
	lock sync.RWMutex
}

// NewTrieV1 創(chuàng)建一個新的TrieV1樹
func NewTrieV1() *TrieV1 {
	return &TrieV1{
		root: &TrieV1Node{
			children: make(map[rune]*TrieV1Node),
			isEnd:    false,
		},
	}
}

// Insert 將一個敏感詞插入到TrieV1樹中
func (t *TrieV1) Insert(word string) {
	t.lock.Lock()
	defer t.lock.Unlock()

	node := t.root
	for _, char := range []rune(word) {
		if _, ok := node.children[char]; !ok {
			node.children[char] = &TrieV1Node{
				children: make(map[rune]*TrieV1Node),
				isEnd:    false,
				parent:   node,
				Value:    char,
			}
		}
		node = node.children[char]
	}

	node.Text = word
	node.isEnd = true
}

// Contains 檢測文本中是否包含敏感詞
func (t *TrieV1) Contains(text string) bool {
	t.lock.RLock()
	defer t.lock.RUnlock()

	node := t.root
	for _, char := range []rune(text) {
		if _, ok := node.children[char]; !ok {
			continue
		}
		node = node.children[char]
		if node.isEnd {
			return true
		}
	}
	return false
}

// Check 檢測文本中是否包含敏感詞,并返回第一個敏感詞
func (t *TrieV1) Check(text string) string {
	t.lock.RLock()
	defer t.lock.RUnlock()

	node := t.root
	for _, char := range text {
		if _, ok := node.children[char]; !ok {
			continue
		}
		node = node.children[char]
		if node.isEnd {
			return node.Text
		}
	}

	return ""
}

// Rebuild 重新構(gòu)建敏感詞樹
func (t *TrieV1) Rebuild(words []string) {
	t.lock.Lock()
	defer t.lock.Unlock()

	t.root = &TrieV1Node{}

	for _, word := range words {
		t.Insert(word)
	}
}

// Delete 刪除一個敏感詞
func (t *TrieV1) Delete(word string) {
	t.lock.Lock()
	defer t.lock.Unlock()

	node := t.root

	for _, char := range []rune(word) {
		if _, ok := node.children[char]; !ok {
			return
		}
		node = node.children[char]

		if node.isEnd {
			node.isEnd = false
			node.Text = ""

			if len(node.children) > 0 { // 有子節(jié)點,不能刪除
				break
			}

			// 遞歸刪除
			t.doDel(node)
		}

	}
}

func (t *TrieV1) doDel(node *TrieV1Node) {
	// 再次判斷是否可以刪除
	if node == nil || len(node.children) > 0 {
		return
	}

	// 從上級節(jié)點的children中刪除本節(jié)點
	delete(node.parent.children, node.Value)

	// 判斷上一層節(jié)點是否可以刪除
	t.doDel(node.parent)
}

在上面的版本中,我們添加了讀寫鎖來保證并發(fā)安全,并且添加了刪除敏感詞的功能。

敏感詞庫的變更,是一個并不頻繁的操作,而可以預(yù)見的時,敏感詞庫不會太大。所以,我們是否可以在敏感詞庫發(fā)生變更時,直接重構(gòu)整個敏感詞庫,在重構(gòu)完成后,再切換到新的敏感詞庫上呢?

測試代碼:

package sensitivewordcheck

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

var trieV1 *TrieV1

func init() {
	trieV1 = NewTrieV1()
	for _, word := range sensitiveWords {
		trieV1.Insert(word)
	}
}

func TestCheckWordAndDelete(t *testing.T) {

	// 添加敏感詞 非法捕魚
	trieV1.Insert("非法捕魚")

	assert.Equal(t, trieV1.Contains("你要去非法捕魚嗎?"), true)

	// 添加敏感詞 非法打獵
	trieV1.Insert("非法打獵")

	assert.Equal(t, trieV1.Contains("你要去非法打獵嗎?"), true)

	// 刪除敏感詞 非法打獵
	trieV1.Delete("非法打獵")

	// 不再包含 非法打獵
	assert.Equal(t, trieV1.Contains("你要去非法打獵嗎?"), false)

	// 非法捕魚 不受影響
	assert.Equal(t, trieV1.Contains("你要去非法捕魚嗎?"), true)

	// 更長的敏感詞
	trieV1.Insert("非法捕魚工具")
	assert.Equal(t, trieV1.Contains("你要去買非法捕魚工具嗎?"), true)

	// 刪除 非法捕魚
	trieV1.Delete("非法捕魚")
	assert.Equal(t, trieV1.Contains("你要去非法捕魚嗎?"), false)
	// 如果有子節(jié)點,不刪除
	assert.Equal(t, trieV1.Contains("你要去買非法捕魚工具嗎?"), true)

}

上面的測試用例中,我們添加了添加、刪除敏感詞功能,并校驗了刪除敏感詞的正確性,以及在有更長的敏感詞時是否會無刪除。 上述用例在本機測試通過。

后記

以上,我們實現(xiàn)了一個簡單的敏感詞過濾功能。實際上,敏感詞過濾還可以做得更復(fù)雜,添加更多功能,比如,檢測拼音、過濾特殊字符等等。這些功能,可以在上面的代碼基礎(chǔ)上,自行擴展。但是需要考慮的是:擴展功能的同時,是否會影響性能,尤其是在檢測超長文本時。

到此這篇關(guān)于使用Go語言實現(xiàn)敏感詞過濾功能的文章就介紹到這了,更多相關(guān)Go敏感詞過濾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Golong實現(xiàn)JWT身份驗證的詳細過程

    使用Golong實現(xiàn)JWT身份驗證的詳細過程

    JWT提供了一種強大而靈活的方法來處理Web應(yīng)用程序中的身份驗證和授權(quán),本教程將引導(dǎo)您逐步實現(xiàn)Go應(yīng)用程序中的JWT身份驗證過程,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • go語言中的log 包示例詳解

    go語言中的log 包示例詳解

    Go語言的log包提供了用于記錄日志的基本功能,相比fmt包,增加了時間戳、日志級別等日志管理功能,非常適合用于調(diào)試和記錄運行信息,本文呢介紹go語言中的log 包,感興趣的朋友一起看看吧
    2024-11-11
  • RabbitMQ延時消息隊列在golang中的使用詳解

    RabbitMQ延時消息隊列在golang中的使用詳解

    延時隊列常使用在某些業(yè)務(wù)場景,使用延時隊列可以簡化系統(tǒng)的設(shè)計和開發(fā)、提高系統(tǒng)的可靠性和可用性、提高系統(tǒng)的性能,下面我們就來看看如何在golang中使用RabbitMQ的延時消息隊列吧
    2023-11-11
  • 詳解Go語言如何檢查系統(tǒng)命令是否可用

    詳解Go語言如何檢查系統(tǒng)命令是否可用

    這篇文章主要為大家詳細介紹了Go語言通過編寫一個函數(shù),利用Go語言標(biāo)準(zhǔn)庫中的功能來檢查系統(tǒng)命令是否可用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • GO語言中embed簡介

    GO語言中embed簡介

    這篇文章主要介紹了GO語言中embed簡介的相關(guān)資料,需要的朋友可以參考下
    2023-08-08
  • Go使用proto3的踩坑實戰(zhàn)記錄

    Go使用proto3的踩坑實戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于Go使用proto3的踩坑記錄,文中通過實例代碼介紹的非常詳細,對大家學(xué)習(xí)或者會用Go語言具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2023-02-02
  • 如何在?Go語言中使用日志包

    如何在?Go語言中使用日志包

    這篇文章主要介紹了如何在?Go語言中使用日志包,日志文件就是一種快速找到這些?bug,更好地了解程序工作狀態(tài)的方法,下文基于go語言介紹該詳細需要的小伙伴可以參考一下
    2022-04-04
  • 淺析Golang中變量與常量的聲明與使用

    淺析Golang中變量與常量的聲明與使用

    變量、常量的聲明與使用是掌握一門編程語言的基礎(chǔ),這篇文章主要為大家詳細介紹了Golang中變量與常量的聲明與使用,需要的可以參考一下
    2023-04-04
  • 詳解Golang語言HTTP客戶端實踐

    詳解Golang語言HTTP客戶端實踐

    本文主要介紹了Golang語言HTTP客戶端實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 詳解Golang中哪些類型可以作為map的key

    詳解Golang中哪些類型可以作為map的key

    在 Go 語言中,map 是一種內(nèi)置的關(guān)聯(lián)數(shù)據(jù)結(jié)構(gòu)類型,由一組無序的鍵值對組成,每個鍵都是唯一的,并與一個對應(yīng)的值相關(guān)聯(lián),本文將詳細介紹哪些類型的變量可以作為 map 的鍵,并通過實例進行說明,感興趣的朋友可以參考下
    2024-01-01

最新評論