<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于 Go 實(shí)現(xiàn) Deno upgrade

          共 4122字,需瀏覽 9分鐘

           ·

          2022-04-28 23:16

          怕什么真理無窮,進(jìn)一寸有一寸的歡喜。大家好,我是@洛竹,一名熱愛編程、熱愛生活的終身學(xué)習(xí)實(shí)踐者。

          點(diǎn)擊上方“Go語言進(jìn)階學(xué)習(xí)”,進(jìn)行關(guān)注

          回復(fù)“Go語言”即可獲贈Python從入門到進(jìn)階共10本電子書

          曉月過殘壘,繁星宿故關(guān)。

          書接上篇,我在向 Deno 學(xué)習(xí)優(yōu)秀的腳本管理中向大家介紹了 Deno 是如何管理它的安裝包的——以 Github release 的形式發(fā)布、執(zhí)行編寫好的 shell 腳本安裝程序以及基于 tags 的版本管理。有版本管理就會有更新的需求,本文就是在研讀了 Deno 的 upgrade 命令后使用 Go 語言實(shí)現(xiàn)了自己的 upgrade 命令。

          獲取最新版本

          我們先來看下 Deno 的源碼:

          use?deno_runtime::deno_fetch::reqwest::Client;
          const?RELEASE_URL:?&str?=?"https://github.com/denoland/deno/releases";
          ...
          async?fn?get_latest_release_version(
          ??client:?&Client,
          )?->?Result<String,?AnyError>?{
          ??println!("Looking?up?latest?version");

          ??let?res?=?client
          ????.get(&format!("{}/latest",?RELEASE_URL))
          ????.send()
          ????.await?;
          ??let?version?=?res.url().path_segments().unwrap().last().unwrap();

          ??Ok(version.replace("v",?""))
          }

          分析出以上代碼做了以下幾件事:

          1. 由于是異步函數(shù),用 println 函數(shù)提示正在查找新版本
          2. 使用 GET 方式請求 https://github.com/denoland/deno/releases/latest
          3. 由于 https://github.com/denoland/deno/releases/latest 會重定向到最新的 release https://github.com/denoland/deno/releases/tag/v1.7.1,通過一頓字符串操作我們便取出了 v1.7.1
          4. 調(diào)用字符串的 replace 方法替換 v"" 得到版本號

          讓我們用 Go 來實(shí)現(xiàn)它:

          代碼看起來差不多,比如模板字符串寫法、字符串處理

          package?release

          import?(
          ?"net/http"
          ?"strings"
          )

          func?getLatestVersion()?string{
          ?releaseURL?:=?fmt.Sprintf("https://github.com/%s/%s/releases/latest",?user,?repo)
          ?resp,?_?:=?http.Get(releaseURL)
          ?defer?resp.Body.Close()?//?為了防止內(nèi)存泄漏

          ?pathArr?:=?strings.Split(resp.Request.URL.Path,?"/")
          ?latest?:=?strings.Replace(pathArr[len(pathArr)-1],?"v",?"",?1)
          ?return?latest
          }

          版本檢測

          版本的處理少不了SemVer。我們使用 go-version 來處理版本相關(guān)工作,有了版本比較我們便可以實(shí)現(xiàn)一個版本檢查的功能。以下代碼是 我封裝的 go-release 中的一段代碼:

          type?UpdateInfo?struct?{
          ?IsUpdate??????bool
          ?LatestVersion?string
          }

          func?CheckUpdate(user?string,?repo?string,?current?string)?(updateInfo?*UpdateInfo,?err?error)?{
          ?releaseURL?:=?fmt.Sprintf("https://github.com/%s/%s/releases/latest",?user,?repo)
          ?resp,?err?:=?http.Get(releaseURL)
          ?if?err?!=?nil?{
          ??return?nil,?err
          ?}
          ?defer?resp.Body.Close()

          ?current?=?strings.Replace(current,?"v",?"",?1)
          ?pathArr?:=?strings.Split(resp.Request.URL.Path,?"/")
          ?latest?:=?strings.Replace(pathArr[len(pathArr)-1],?"v",?"",?1)

          ?currentVersion,?err?:=?version.NewVersion(current)
          ?if?err?!=?nil?{
          ??return?nil,?err
          ?}
          ?latestVersion,?err?:=?version.NewVersion(latest)
          ?if?err?!=?nil?{
          ??return?nil,?err
          ?}
          ?updateInfo?=?&UpdateInfo{
          ??IsUpdate:??????currentVersion.LessThan(latestVersion),
          ??LatestVersion:?latest,
          ?}
          ?return?updateInfo,?nil
          }

          cobra 實(shí)現(xiàn) upgrade

          下面的代碼中,我們基于 go-release 實(shí)現(xiàn)了一個帶 upgrade 命令的簡易 CLI,核心邏輯便是比較本地版本是否是最新的,如果不是則安裝最新的。

          const?Version?=?"0.0.1"

          func?checkUpgrade(current?string)?{
          ??fmt.Println("Looking?up?latest?version")
          ?update,?err?:=?release.CheckUpdate("youngjuning",?"tpc",?current)
          ?if?err?!=?nil?{
          ??panic(err)
          ?}
          ?if?update.IsUpdate?{
          ??fmt.Printf("Found?latest?version?%v?\n",?update.LatestVersion)
          ??sh.Command("bash",?"-c",?"curl?-fsSL?https://raw.githubusercontent.com/youngjuning/tpc/main/install.sh?|?sh").Run()
          ?}?else?{
          ??fmt.Printf("Local?version?%v?is?the?most?recent?release?\n",?current)
          ?}
          }

          var?rootCmd?=?&cobra.Command{
          ?Use:?????"app",
          ?Version:?Version,
          }

          var?cmdUpgrade?=?&cobra.Command{
          ?Use:?"upgrade",
          ?Run:?func(cmd?*cobra.Command,?args?[]string)?{
          ??checkUpgrade(Version,?force)
          ?},
          }

          func?main()?{
          ?rootCmd.AddCommand(cmdUpgrade)
          ?rootCmd.Execute()
          }

          強(qiáng)制更新方案

          Node.js 命令行工具檢查更新的正確姿勢 對這個問題做了很深入的研究并實(shí)現(xiàn)了 Node 版的工具。核心邏輯就是每次執(zhí)行命令時異步去執(zhí)行檢查更新。這句話翻譯成 Go 就是用協(xié)程去執(zhí)行檢查更新的動作,這樣執(zhí)行命令還是會立馬得到反饋,程序則會在后臺執(zhí)行檢查更新,當(dāng)檢測到有新版本則強(qiáng)制更新。

          完整代碼在go-release/example,對 Cobra 不熟悉的同學(xué)可以看一下 Cobra 中文文檔。

          執(zhí)行 shell 命令推薦 go-sh,它對 exec 包做了封裝,提供了更好地使用體驗(yàn)( PS:還不是因?yàn)槲也耍?/p>

          //?rootCmd?代表沒有調(diào)用子命令時的基礎(chǔ)命令
          var?rootCmd?=?&cobra.Command{
          ?Use:?????"tpc",
          ?Version:?Version,
          ?Run:?func(cmd?*cobra.Command,?args?[]string)?{
          ??sh.Command("tpc",?"-h").Run()
          ??},
          ??//?每次執(zhí)行完命令后去執(zhí)行檢查更新,Start?表示不阻塞原來的任務(wù),還有一個?Run?方法則是會阻塞
          ?PersistentPostRun:?func(cmd?*cobra.Command,?args?[]string)?{
          ??sh.Command("bash",?"-c",?"tpc?upgrade?--force=false").Start()
          ?},
          }

          go-release 的誕生

          go-release 核心代碼翻譯自 Deno 的 upgrade,開源項(xiàng)目,點(diǎn)贊是我維護(hù)的動力,在此求個 Star。

          go-release 的誕生源自我工作中要實(shí)現(xiàn)一個 CLI 工具的版本管理功能,由于是個菜鳥,中間遇到了各種各樣的困難,幸得大佬無私地解答,才能很快實(shí)現(xiàn)了這么一個功能,在此鳴謝:

          林小帥:

          漫畫 Go 語言 純手繪版 作者好家伙:

          justjavac 大佬:

          -------------------?End?-------------------


          往期精彩文章推薦:

          歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持

          想加入Go學(xué)習(xí)群請?jiān)诤笈_回復(fù)【入群

          萬水千山總是情,點(diǎn)個【在看】行不行

          瀏覽 24
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费国产黄片在线看 | 黄色一及A片 | 婷婷色丁香五月 | 不卡的a12在线观看 | 国产成人av 高清在线 |