日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

Go-Zero 是如何做路由管理的?

來源: 責(zé)編: 時(shí)間:2023-08-09 23:03:50 397觀看
導(dǎo)讀go-zero 是一個(gè)微服務(wù)框架,包含了 web 和 rpc 兩大部分。而對于 web 框架來說,路由管理是必不可少的一部分,那么本文就來探討一下 go-zero 的路由管理是怎么做的,具體采用了哪種技術(shù)方案。路由管理方案路由管理方案有很多

c8w28資訊網(wǎng)——每日最新資訊28at.com

go-zero 是一個(gè)微服務(wù)框架,包含了 web 和 rpc 兩大部分。c8w28資訊網(wǎng)——每日最新資訊28at.com

而對于 web 框架來說,路由管理是必不可少的一部分,那么本文就來探討一下 go-zero 的路由管理是怎么做的,具體采用了哪種技術(shù)方案。c8w28資訊網(wǎng)——每日最新資訊28at.com

路由管理方案

路由管理方案有很多種,具體應(yīng)該如何選擇,應(yīng)該根據(jù)使用場景,以及實(shí)現(xiàn)的難易程度做綜合分析,下面介紹常見的三種方案。c8w28資訊網(wǎng)——每日最新資訊28at.com

注意這里只是做一個(gè)簡單的概括性對比。c8w28資訊網(wǎng)——每日最新資訊28at.com

標(biāo)準(zhǔn)庫方案

最簡單的方案就是直接使用 map[string]func() 作為路由的數(shù)據(jù)結(jié)構(gòu),鍵為具體的路由,值為具體的處理方法。c8w28資訊網(wǎng)——每日最新資訊28at.com

// 路由管理數(shù)據(jù)結(jié)構(gòu)type ServeMux struct {    mu    sync.RWMutex          // 對象操作讀寫鎖    m     map[string]muxEntry   // 存儲路由映射關(guān)系}

這種方案優(yōu)點(diǎn)就是實(shí)現(xiàn)簡單,性能較高;缺點(diǎn)也很明顯,占用內(nèi)存更高,更重要的是不夠靈活。c8w28資訊網(wǎng)——每日最新資訊28at.com

Trie Tree

Trie Tree 也稱為字典樹或前綴樹,是一種用于高效存儲和檢索、用于從某個(gè)集合中查到某個(gè)特定 key 的數(shù)據(jù)結(jié)構(gòu)。c8w28資訊網(wǎng)——每日最新資訊28at.com

圖片c8w28資訊網(wǎng)——每日最新資訊28at.com

Radix Tree 通過合并公共前綴來降低存儲空間的開銷,避免了 Trie Tree 字符串過長和字符集過大時(shí)導(dǎo)致的存儲空間過多問題,同時(shí)公共前綴優(yōu)化了路徑層數(shù),提升了插入、查詢、刪除等操作效率。c8w28資訊網(wǎng)——每日最新資訊28at.com

比如 Gin 框架使用的開源組件 HttpRouter 就是采用這個(gè)方案。c8w28資訊網(wǎng)——每日最新資訊28at.com

go-zero 路由規(guī)則

在使用 go-zero 開發(fā)項(xiàng)目時(shí),定義路由需要遵守如下規(guī)則:c8w28資訊網(wǎng)——每日最新資訊28at.com

  1. 路由必須以 / 開頭
  2. 路由節(jié)點(diǎn)必須以 / 分隔
  3. 路由節(jié)點(diǎn)中可以包含 :,但是 : 必須是路由節(jié)點(diǎn)的第一個(gè)字符,: 后面的節(jié)點(diǎn)值必須要在結(jié)請求體中有 path tag 聲明,用于接收路由參數(shù)
  4. 路由節(jié)點(diǎn)可以包含字母、數(shù)字、下劃線、中劃線

接下來就讓我們深入到源碼層面,相信看過源碼之后,你就會更懂這些規(guī)則的意義了。c8w28資訊網(wǎng)——每日最新資訊28at.com

go-zero 源碼實(shí)現(xiàn)

首先需要說明的是,底層數(shù)據(jù)結(jié)構(gòu)使用的是二叉搜索樹,還不是很了解的同學(xué)可以看這篇文章:使用 Go 語言實(shí)現(xiàn)二叉搜索樹。c8w28資訊網(wǎng)——每日最新資訊28at.com

節(jié)點(diǎn)定義

先看一下節(jié)點(diǎn)定義:c8w28資訊網(wǎng)——每日最新資訊28at.com

// core/search/tree.goconst (    colon = ':'    slash = '/')type (    // 節(jié)點(diǎn)    node struct {        item     interface{}        children [2]map[string]*node    }    // A Tree is a search tree.    Tree struct {        root *node    })

重點(diǎn)說一下 children,它是一個(gè)包含兩個(gè)元素的數(shù)組,元素 0 存正常路由鍵,元素 1 存以 : 開頭的路由鍵,這些是 url 中的變量,到時(shí)候需要替換成實(shí)際值。c8w28資訊網(wǎng)——每日最新資訊28at.com

舉一個(gè)例子,有這樣一個(gè)路由 /api/:user,那么 api 會存在 children[0],user 會存在 children[1]。c8w28資訊網(wǎng)——每日最新資訊28at.com

具體可以看看這段代碼:c8w28資訊網(wǎng)——每日最新資訊28at.com

func (nd *node) getChildren(route string) map[string]*node {    // 判斷路由是不是以 : 開頭    if len(route) > 0 && route[0] == colon {        return nd.children[1]    }    return nd.children[0]}

路由添加

// Add adds item to associate with route.func (t *Tree) Add(route string, item interface{}) error {    // 需要路由以 / 開頭    if len(route) == 0 || route[0] != slash {        return errNotFromRoot    }    if item == nil {        return errEmptyItem    }    // 把去掉 / 的路由作為參數(shù)傳入    err := add(t.root, route[1:], item)    switch err {    case errDupItem:        return duplicatedItem(route)    case errDupSlash:        return duplicatedSlash(route)    default:        return err    }}func add(nd *node, route string, item interface{}) error {    if len(route) == 0 {        if nd.item != nil {            return errDupItem        }        nd.item = item        return nil    }    // 繼續(xù)判斷,看看是不是有多個(gè) /    if route[0] == slash {        return errDupSlash    }    for i := range route {        // 判斷是不是 /,目的就是去處兩個(gè) / 之間的內(nèi)容        if route[i] != slash {            continue        }        token := route[:i]                // 看看有沒有子節(jié)點(diǎn),如果有子節(jié)點(diǎn),就在子節(jié)點(diǎn)下面繼續(xù)添加        children := nd.getChildren(token)        if child, ok := children[token]; ok {            if child != nil {                return add(child, route[i+1:], item)            }            return errInvalidState        }        // 沒有子節(jié)點(diǎn),那么新建一個(gè)        child := newNode(nil)        children[token] = child        return add(child, route[i+1:], item)    }    children := nd.getChildren(route)    if child, ok := children[route]; ok {        if child.item != nil {            return errDupItem        }        child.item = item    } else {        children[route] = newNode(item)    }    return nil}

主要部分代碼都已經(jīng)加了注釋,其實(shí)這個(gè)過程就是樹的構(gòu)建,如果讀過之前那篇文章,那這里還是比較好理解的。c8w28資訊網(wǎng)——每日最新資訊28at.com

路由查找

先來看一段 match 代碼:c8w28資訊網(wǎng)——每日最新資訊28at.com

func match(pat, token string) innerResult {    if pat[0] == colon {        return innerResult{            key:   pat[1:],            value: token,            named: true,            found: true,        }    }    return innerResult{        found: pat == token,    }}

這里有兩個(gè)參數(shù):c8w28資訊網(wǎng)——每日最新資訊28at.com

  • pat:路由樹中存儲的路由。
  • token:實(shí)際請求的路由,可能包含參數(shù)值。

還是剛才的例子 /api/:user,如果是 api,沒有以 : 開頭,那就不會走 if 邏輯。c8w28資訊網(wǎng)——每日最新資訊28at.com

接下來匹配 :user 部分,如果實(shí)際請求的 url 是 /api/zhangsan,那么會將 user 作為 key,zhangsan 作為 value 保存到結(jié)果中。c8w28資訊網(wǎng)——每日最新資訊28at.com

下面是搜索查找代碼:c8w28資訊網(wǎng)——每日最新資訊28at.com

// Search searches item that associates with given route.func (t *Tree) Search(route string) (Result, bool) {    // 第一步先判斷是不是 / 開頭    if len(route) == 0 || route[0] != slash {        return NotFound, false    }    var result Result    ok := t.next(t.root, route[1:], &result)    return result, ok}func (t *Tree) next(n *node, route string, result *Result) bool {    if len(route) == 0 && n.item != nil {        result.Item = n.item        return true    }    for i := range route {        // 和 add 里同樣的提取邏輯        if route[i] != slash {            continue        }        token := route[:i]        return n.forEach(func(k string, v *node) bool {            r := match(k, token)            if !r.found || !t.next(v, route[i+1:], result) {                return false            }            // 如果 url 中有參數(shù),會把鍵值對保存到結(jié)果中            if r.named {                addParam(result, r.key, r.value)            }            return true        })    }    return n.forEach(func(k string, v *node) bool {        if r := match(k, route); r.found && v.item != nil {            result.Item = v.item            if r.named {                addParam(result, r.key, r.value)            }            return true        }        return false    })}

以上就是路由管理的大部分代碼,整個(gè)文件也就 200 多行,邏輯也并不復(fù)雜,通讀之后還是很有收獲的。c8w28資訊網(wǎng)——每日最新資訊28at.com

大家如果感興趣的話,可以找到項(xiàng)目更詳細(xì)地閱讀。也可以關(guān)注我,接下來還會分析其他模塊的源碼。c8w28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-5196-0.htmlGo-Zero 是如何做路由管理的?

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 我們一起聊聊抽象工廠模式(AbstractFactoty)

下一篇: 三言兩語說透webpack對vue的編譯

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
亚洲欧美日韩综合一区| 伊人色综合久久天天五月婷| 欧美国产高清| 欧美激情小视频| 欧美日韩成人综合在线一区二区| 在线看片一区| 亚洲国产婷婷香蕉久久久久久99| 欧美视频在线播放| 国产精品久久九九| 国产无一区二区| 亚洲激情网站| 亚洲欧美日韩国产中文在线| 久久国产欧美| 欧美激情一区| 国产精品美女一区二区| 极品av少妇一区二区| 99精品欧美一区二区三区| 亚洲综合电影一区二区三区| 久久人人97超碰人人澡爱香蕉| 欧美一区二区高清| 免费不卡欧美自拍视频| 欧美午夜剧场| 一区二区在线不卡| 亚洲图片在线观看| 久久久久国产精品人| 欧美日韩另类在线| 国内精品久久久久久 | 久久久久久九九九九| 激情国产一区二区| 亚洲人成人99网站| 亚洲在线一区| 欧美成人精品1314www| 国产精品老女人精品视频| 亚洲高清视频一区| 午夜精彩国产免费不卡不顿大片| 亚洲在线国产日韩欧美| 噜噜噜噜噜久久久久久91| 国产精品久久久久久久久久妞妞| 国产精品黄视频| 亚洲大胆在线| 欧美一区二区久久久| 欧美日韩美女| 在线看视频不卡| 亚洲一区二区视频在线| 欧美电影免费观看| 国内精品一区二区三区| 亚洲一区中文| 欧美欧美天天天天操| 国语自产精品视频在线看抢先版结局 | 久久精品人人做人人综合| 欧美连裤袜在线视频| 黄色欧美日韩| 欧美亚洲色图校园春色| 欧美日韩在线观看一区二区| 伊人精品久久久久7777| 欧美一级理论片| 欧美性色aⅴ视频一区日韩精品| 国产欧美日韩一区二区三区在线| 国产日韩av一区二区| 9色porny自拍视频一区二区| 理论片一区二区在线| 国产日韩精品在线观看| 亚洲一级高清| 欧美日韩精品三区| 亚洲国产精品va在线观看黑人| 一区二区三区高清在线| 久久这里只有| 国内一区二区三区| 欧美在线观看视频| 国产精品有限公司| 亚洲综合欧美日韩| 国产精品qvod| 一本到高清视频免费精品| 欧美高清视频www夜色资源网| 国产精品久久久久一区| 亚洲伦理中文字幕| 欧美日本不卡高清| 亚洲精品乱码久久久久久按摩观| 午夜精品一区二区三区四区| 欧美日韩国产999| 亚洲精品社区| 欧美精品尤物在线| 亚洲乱码国产乱码精品精| 欧美成人免费全部| 亚洲激情在线播放| 欧美高清日韩| 亚洲精品字幕| 欧美另类极品videosbest最新版本| 国产午夜亚洲精品不卡| 亚洲午夜一区二区三区| 国产精品r级在线| 亚洲欧美成人| 国产区二精品视| 久久精品亚洲精品| 影音先锋一区| 另类天堂视频在线观看| 亚洲国产精品久久久久久女王| 欧美亚洲一区二区在线| 国产精品私人影院| 欧美一区成人| 伊人一区二区三区久久精品| 米奇777超碰欧美日韩亚洲| 亚洲激情黄色| 欧美日韩免费观看一区三区| 亚洲性xxxx| 国产乱码精品一区二区三区五月婷 | 在线观看一区二区视频| 美女国内精品自产拍在线播放| 国产精品久久久久一区二区三区 | 国产一区二区三区黄| 欧美在线观看视频一区二区| 国内免费精品永久在线视频| 久久综合伊人77777| 最新热久久免费视频| 欧美日韩午夜在线| 午夜久久久久久| 在线不卡视频| 欧美日韩国产区| 亚洲欧美日韩另类| 激情亚洲一区二区三区四区| 欧美刺激性大交免费视频| 一区二区三区高清视频在线观看| 欧美国产在线观看| 在线一区视频| 国产一区二区中文| 欧美国产三区| 亚洲欧美国产另类| 国内精品亚洲| 欧美日韩激情小视频| 午夜在线观看欧美| 亚洲国产美女| 国产精品乱人伦一区二区| 久久裸体视频| 亚洲视频axxx| 一区二区在线看| 欧美午夜电影在线观看| 久久久久久夜| 中国av一区| 狠狠爱成人网| 欧美日韩在线直播| 久久久水蜜桃| 亚洲视频二区| 在线电影一区| 国产精品视频导航| 欧美大片一区| 午夜久久一区| 91久久久久久久久| 国产精品一卡| 欧美国产成人在线| 午夜精品视频| 亚洲人成人99网站| 国产日韩一区欧美| 欧美日产一区二区三区在线观看| 夜夜嗨网站十八久久| 国产一区二区三区久久久| 欧美日韩精品久久久| 久久国产日韩| 亚洲视频在线免费观看| 在线精品一区| 国产精品丝袜久久久久久app| 午夜在线成人av| 亚洲激情自拍| 国产视频亚洲| 国产精品久久久久久av下载红粉| 香蕉久久一区二区不卡无毒影院| 国产欧美一区二区在线观看| 欧美另类在线观看| 久久久夜精品| 香蕉尹人综合在线观看| 夜夜爽夜夜爽精品视频| 亚洲福利视频一区二区| 国产亚洲精品资源在线26u| 国产精品成人观看视频免费| 葵司免费一区二区三区四区五区| 亚洲人成人一区二区在线观看| 欧美日韩免费网站| 久久一区二区三区四区五区| 欧美一区二区三区免费观看 | 亚洲欧洲综合| 在线欧美视频| 国内精品99| 国产欧美精品| 欧美日韩中文字幕| 欧美精品福利| 欧美成人午夜剧场免费观看| 久久久久久欧美| 欧美一区二区在线看| 亚洲综合二区| 亚洲午夜在线视频| 一区二区91| 亚洲美女免费视频| 最新精品在线| 在线精品视频一区二区| 在线观看日韩av先锋影音电影院| 欧美特黄一区| 欧美日韩成人一区| 欧美大片在线观看| 欧美暴力喷水在线| 美腿丝袜亚洲色图| 蜜桃av噜噜一区| 美女精品在线观看| 蜜桃视频一区| 欧美aa国产视频| 欧美 日韩 国产精品免费观看|