golang实现前缀数实现匹配路由和获取路由参数

文章目录


前言

golang实现前缀数实现匹配路由和获取路由参数:


一、前缀树是什么?

前缀树:

又称单词查找树,字典树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

二、需求定义

使用前缀树 匹配路由

提取路由上的参数规则: 定义路由/v1/{a},其中a就是参数名,请求路由/v1/123,那么a=123

可以定义多个参数, 如: 定义路由/v1/{a}/{b}/{c},其中就有 a,b,c 3个路由参数

必须匹配完,如: 定义路由/v1/{a}/{b}则/v1/123/456能匹配上,/v1/123不能匹配上

不允许的规则,如: /v1/* /v1/{a} 两个都不能用,相互冲突

代码如下(示例):

go 复制代码
package main

import (
	"log"
	"strings"
)

// 前缀树结构
type Trie struct {
	next map[string]*Trie
	isWord bool
}

func NewTrie() Trie {
	root := new(Trie)
	root.next = make(map[string]*Trie)
	root.isWord = false
	return *root
}

// 插入数据, 路由根据 "/" 进行拆分
func (t *Trie) Insert(word string) {
	for _, v := range strings.Split(word, "/") {
		if t.next[v] == nil {
			node := new(Trie)
			node.next = make(map[string]*Trie)
			node.isWord = false
			t.next[v] = node
		}
		// * 匹配所有
		// {X}  匹配路由参数 X
		if v == "*" || strings.Index(v, "{") != -1 {
			t.isWord = true
		}
		t = t.next[v]
	}
	t.isWord = true
}

// 匹配路由
func (t *Trie) Search(word string) (isHave bool, arg map[string]string) {
	arg = make(map[string]string)
	isHave = false
	for _, v := range strings.Split(word, "/") {
		if t.isWord {
			for k,_ := range t.next {
				if strings.Index(k, "{") != -1 {
					key := strings.Replace(k, "{", "", -1)
					key = strings.Replace(key, "}", "", -1)
					arg[key] = v
				}
				v = k
			}
			//log.Println("v = ", v)
		}
		if t.next[v] == nil {
			log.Println("找不到了, 匹配不上")
			return
		}
		t = t.next[v]
	}
	//log.Println(t.next, len(t.next))
	// 必须匹配全  比如: /v1/{b}/{a}  /v1/123匹配不到, /v1/123/456才可匹配
	if len(t.next) == 0 {
		isHave = t.isWord
		return
	}
	return
}

// 打印树
func (t *Trie) Show(){
Loop:
	if t == nil {
		log.Println("end")
		return
	}
	log.Println(t)
	for _, v :=range t.next {
		t = v
		goto Loop
	}

}

func main(){

	// 1. 使用前缀树 匹配路由
	// 2. 提取路由上的参数规则:  定义路由/v1/{a},其中a就是参数名,请求路由/v1/123,那么a=123
	// 3. 可以定义多个参数, 如: 定义路由/v1/{a}/{b}/{c},其中就有 a,b,c 3个路由参数
	// 4. 必须匹配完,如: 定义路由/v1/{a}/{b}则/v1/123/456能匹配上,/v1/123不能匹配上
	// 5. 不允许的规则,如:  /v1/*  /v1/{a}  两个都不能用,相互冲突

	t := NewTrie()
	t.Insert("/")
	t.Insert("H/e/c/{b}/{a}")
	t.Insert("a/e/c/l/o")
	t.Insert("e/c/c/*")// 任意的 无法取 *的值
	t.Insert("e/c/c/{a}/{a}") // 只取后一个a
	t.Insert("/v1/*")
	t.Insert("/v1/{a}")
	t.Show()
	//isok, cs := t.Search("H/e/c/asdasd/asdasd")
	//isok, cs := t.Search("/v1/123")
	isok, cs := t.Search("/")
	log.Println(isok, cs)

	//fmt.Print(t.Search("H/e/l/l/aaa"),"\n")

}
相关推荐
萧鼎26 分钟前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸27 分钟前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农27 分钟前
Python 继承、多态、封装、抽象
开发语言·python
^velpro^28 分钟前
数据库连接池的创建
java·开发语言·数据库
秋の花36 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端39 分钟前
第六章 7.0 LinkList
java·开发语言·网络
可峰科技1 小时前
斗破QT编程入门系列之二:认识Qt:编写一个HelloWorld程序(四星斗师)
开发语言·qt
全栈开发圈1 小时前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫
面试鸭1 小时前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
小白学大数据1 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫