<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:如何獲得項(xiàng)目根目錄?

          共 2767字,需瀏覽 6分鐘

           ·

          2021-11-05 15:12

          閱讀本文大概需要 5 分鐘。

          大家好,我是 polarisxu。

          項(xiàng)目中,特別是 Web 項(xiàng)目,經(jīng)常需要獲得項(xiàng)目的根目錄,進(jìn)而可以訪問(wèn)到項(xiàng)目相關(guān)的其他資源,比如配置文件、靜態(tài)資源文件、模板文件、數(shù)據(jù)文件、日志文件等(Go1.16 后,有些可以方便的通過(guò) embed 內(nèi)嵌進(jìn)來(lái))。比如下面的目錄結(jié)構(gòu):(路徑是 /Users/xuxinhua/stdcwd

          ├──?bin
          ????├──?cwd
          ├──?main.go
          └──?log
          ????├──?error.log

          為了正確讀取 error.log,我們需要獲得項(xiàng)目根目錄。學(xué)完本文知識(shí)可以解決該問(wèn)題。

          解決方案有多種,各有優(yōu)缺點(diǎn)和使用注意事項(xiàng),選擇你喜歡的即可。

          01 使用 os.Getwd

          Go 語(yǔ)言標(biāo)準(zhǔn)庫(kù) os 中有一個(gè)函數(shù) Getwd

          func?Getwd()?(dir?string,?err?error)

          它返回當(dāng)前工作目錄。

          基于此,我們可以得到項(xiàng)目根目錄。還是上面的目錄結(jié)構(gòu),切換到 /Users/xuxinhua/stdcwd,然后執(zhí)行程序:

          $?cd?/Users/xuxinhua/stdcwd
          $?bin/cwd

          這時(shí),當(dāng)前目錄(os.Getwd 的返回值)就是 /Users/xuxinhua/stdcwd。

          但是,如果我們不在這個(gè)目錄執(zhí)行的 bin/cwd,當(dāng)前目錄就變了。因此,這不是一種好的方式。

          不過(guò),我們可以要求必須在 /Users/xuxinhua/stdcwd 目錄運(yùn)行程序,否則報(bào)錯(cuò),具體怎么做到限制,留給你思考。

          02 使用 exec.LookPath

          在上面的目錄結(jié)構(gòu)中,如果我們能夠獲得程序 cwd 所在目錄,也就相當(dāng)于獲得了項(xiàng)目根目錄。

          binary,?err?:=?exec.LookPath(os.Args[0])

          os.Args[0] 是當(dāng)前程序名。如果我們?cè)陧?xiàng)目根目錄執(zhí)行程序 bin/cwd,以上程序返回的 binary 結(jié)果是 bin/cwd,即程序 cwd 的相對(duì)路徑,可以通過(guò) filepath.Abs() 函數(shù)得到絕對(duì)路徑,最后通過(guò)調(diào)用兩次 filepath.Dir 得到項(xiàng)目根目錄。

          binary,?_?:=?exec.LookPath(os.Args[0])
          root?:=?filepath.Dir(filepath.Dir(filepath.Abs(binary)))

          03 使用 os.Executable

          可能是類(lèi)似的需求很常見(jiàn),Go 在 1.8 專(zhuān)門(mén)為這樣的需求增加了一個(gè)函數(shù):

          //?Executable?returns?the?path?name?for?the?executable?that?started?the?current?process.
          //?There?is?no?guarantee?that?the?path?is?still?pointing?to?the?correct?executable.
          //?If?a?symlink?was?used?to?start?the?process,?depending?on?the?operating?system,?the?result?might?be?the?symlink?or?the?path?it?pointed?to.
          //?If?a?stable?result?is?needed,?path/filepath.EvalSymlinks?might?help.
          //?Executable?returns?an?absolute?path?unless?an?error?occurred.
          //?The?main?use?case?is?finding?resources?located?relative?to?an?executable.
          func?Executable()?(string,?error)

          和 exec.LookPath 類(lèi)似,不過(guò)該函數(shù)返回的結(jié)果是絕對(duì)路徑。因此,不需要經(jīng)過(guò) filepath.Abs 處理。

          binary,?_?:=?os.Executable()
          root?:=?filepath.Dir(filepath.Dir(binary))

          注意,exec.LookPath 和 os.Executable 的結(jié)果都是可執(zhí)行程序的路徑,包括可執(zhí)行程序本身,比如 /Users/xuxinhua/stdcwd/bin/cwd

          細(xì)心的讀者可能會(huì)注意到該函數(shù)注釋中提到符號(hào)鏈接問(wèn)題,為了獲得穩(wěn)定的結(jié)果,我們應(yīng)該借助 filepath.EvalSymlinks 進(jìn)行處理。

          package?main

          import?(
          ????"fmt"
          ????"os"
          ????"path/filepath"
          )

          func?main()?{
          ????ex,?err?:=?os.Executable()
          ????if?err?!=?nil?{
          ????????panic(err)
          ????}
          ????exPath?:=?filepath.Dir(ex)
          ????realPath,?err?:=?filepath.EvalSymlinks(exPath)
          ????if?err?!=?nil?{
          ????????panic(err)
          ????}
          ????fmt.Println(filepath.Dir(realPath))
          }

          最后輸出的就是項(xiàng)目根目錄。(如果你的可執(zhí)行文件放在根目錄下,最后的 filepath.Dir 就不需要了)

          注意:exec.LookPath 也有軟鏈接的問(wèn)題。

          exec.LookPath 和 os.Executable 函數(shù),再提醒一點(diǎn),如果使用 go run 方式運(yùn)行,結(jié)果會(huì)是臨時(shí)文件。因此,記得先編譯(這也是比 go run 更好的方式,go run 應(yīng)該只是用來(lái)本地測(cè)試)。

          04 小結(jié)

          既然 Go1.8 為我們專(zhuān)門(mén)提供了這樣一個(gè)函數(shù),針對(duì)本文提到的場(chǎng)景,我們應(yīng)該總是使用它。

          你用的什么方式呢?歡迎留言交流。




          往期推薦


          我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網(wǎng)公司工作,10多年技術(shù)研發(fā)與架構(gòu)經(jīng)驗(yàn)!2012 年接觸 Go 語(yǔ)言并創(chuàng)建了 Go 語(yǔ)言中文網(wǎng)!著有《Go語(yǔ)言編程之旅》、開(kāi)源圖書(shū)《Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)》等。


          堅(jiān)持輸出技術(shù)(包括 Go、Rust 等技術(shù))、職場(chǎng)心得和創(chuàng)業(yè)感悟!歡迎關(guān)注「polarisxu」一起成長(zhǎng)!也歡迎加我微信好友交流:gopherstudio


          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  AA黄色视频 | 日韩爱爱爱爱 | 中国女人一级视频 | av手机在线观看网站 | 精产国品一区二区区别 |