成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

來聊一聊,Go 的相對路徑問題

開發(fā) 前端
go test 在一些場景下也會(huì)遇到路徑問題,因?yàn)間o test只能夠在當(dāng)前目錄執(zhí)行,所以在執(zhí)行測試用例的時(shí)候,你的執(zhí)行目錄已經(jīng)是測試目錄了。

[[415282]]

本文轉(zhuǎn)載自微信公眾號(hào)「腦子進(jìn)煎魚了」,作者陳煎魚。轉(zhuǎn)載本文請聯(lián)系腦子進(jìn)煎魚了公眾號(hào)。

大家好,我是煎魚。

Go 語言中存在各種運(yùn)行方式,如何正確的引用文件路徑成為一個(gè)值得商議的問題

以我的一個(gè)老 Demo gin-blog 為例,當(dāng)我們在項(xiàng)目根目錄下運(yùn)行。

無論是執(zhí)行 go run main.go 時(shí)能夠正常運(yùn)行,執(zhí)行 go build也是正常的。如下:

  1. [$ gin-blog]# go run main.go 
  2. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. 
  3.  - using env:    export GIN_MODE=release 
  4.  - using code:    gin.SetMode(gin.ReleaseMode) 
  5.  
  6. [GIN-debug] GET    /api/v1/tags              --> gin-blog/routers/api/v1.GetTags (3 handlers) 
  7. ... 

在不同的目錄層級下,不同的方式運(yùn)行,又是怎么樣的呢,帶著我們的疑問去學(xué)習(xí)!

問題

go run

我們上移目錄層級,到 $GOPATH/src 下,執(zhí)行 go run gin-blog/main.go

  1. [$ src]# go run gin-blog/main.go 
  2. 2018/03/12 16:06:13 Fail to parse 'conf/app.ini'open conf/app.ini: no such file or directory 
  3. exit status 1 

go build

使用 go build 命令,執(zhí)行 ./gin-blog/main。如下:

  1. [$ src]# ./gin-blog/main 
  2. 2018/03/12 16:49:35 Fail to parse 'conf/app.ini'open conf/app.ini: no such file or directory 

這時(shí)候你要打一個(gè)大大的問號(hào),就是我的程序讀取到什么地方去了?

我們通過分析得知,Go 運(yùn)行的相對路徑是相對于執(zhí)行命令時(shí)的目錄,自然也就讀取不到了。

思考

既然已經(jīng)知道問題的所在點(diǎn),我們就可以尋思做點(diǎn)什么 : )

我們想到相對路徑是相對執(zhí)行命令的目錄,那么我們獲取可執(zhí)行文件的地址,拼接起來不就好了嗎?

實(shí)踐

我們編寫獲取當(dāng)前可執(zhí)行文件路徑的方法:

  1. import ( 
  2.  "path/filepath" 
  3.  "os" 
  4.  "os/exec" 
  5.  "string" 
  6.  
  7. func GetAppPath() string { 
  8.     file, _ := exec.LookPath(os.Args[0]) 
  9.     path, _ := filepath.Abs(file) 
  10.     index := strings.LastIndex(path, string(os.PathSeparator)) 
  11.  
  12.     return path[:index

將其放到啟動(dòng)代碼處查看路徑:

  1. log.Println(GetAppPath()) 

我們分別執(zhí)行以下兩個(gè)命令,查看輸出結(jié)果。

1、 go run

  1. $ go run main.go 
  2. 2018/03/12 18:45:40 /tmp/go-build962610262/b001/exe 

2、 go build

  1. $ ./main 
  2. 2018/03/12 18:49:44 $GOPATH/src/gin-blog 

剖析

我們聚焦在 go run 的輸出結(jié)果上,發(fā)現(xiàn)它是一個(gè)臨時(shí)文件的地址,這是為什么呢?

在go help run中,我們可以看到:

  1. Run compiles and runs the main package comprising the named Go source files. 
  2. A Go source file is defined to be a file ending in a literal ".go" suffix. 

也就是 go run 執(zhí)行時(shí)會(huì)將文件放到 /tmp/go-build... 目錄下,編譯并運(yùn)行。

因此go run main.go出現(xiàn)/tmp/go-build962610262/b001/exe結(jié)果也不奇怪了,因?yàn)樗呀?jīng)跑到臨時(shí)目錄下去執(zhí)行可執(zhí)行文件了。

思考

這就已經(jīng)很清楚了,那么我們想想,會(huì)出現(xiàn)哪些問題呢。如下:

  • 依賴相對路徑的文件,出現(xiàn)路徑出錯(cuò)的問題。
  • go run 和 go build 不一樣,一個(gè)到臨時(shí)目錄下執(zhí)行,一個(gè)可手動(dòng)在編譯后的目錄下執(zhí)行,路徑的處理方式會(huì)不同。
  • 不斷go run,不斷產(chǎn)生新的臨時(shí)文件。

這其實(shí)就是根本原因了,因?yàn)?go run 和 go build 的編譯文件執(zhí)行路徑并不同,執(zhí)行的層級也有可能不一樣,自然而然就出現(xiàn)各種讀取不到的奇怪問題了。

解決方案

一、獲取編譯后的可執(zhí)行文件路徑

1、 將配置文件的相對路徑與GetAppPath()的結(jié)果相拼接,可解決go build main.go的可執(zhí)行文件跨目錄執(zhí)行的問題(如:./src/gin-blog/main)

  1. import ( 
  2.  "path/filepath" 
  3.  "os" 
  4.  "os/exec" 
  5.  "string" 
  6.  
  7. func GetAppPath() string { 
  8.     file, _ := exec.LookPath(os.Args[0]) 
  9.     path, _ := filepath.Abs(file) 
  10.     index := strings.LastIndex(path, string(os.PathSeparator)) 
  11.  
  12.     return path[:index

但是這種方式,對于go run依舊無效,這時(shí)候就需要 2 來補(bǔ)救。

2、 通過傳遞參數(shù)指定路徑,可解決go run的問題

  1. package main 
  2.  
  3. import ( 
  4.     "flag" 
  5.     "fmt" 
  6.  
  7. func main() { 
  8.     var appPath string 
  9.     flag.StringVar(&appPath, "app-path""app-path"
  10.     flag.Parse() 
  11.     fmt.Printf("App path: %s", appPath) 

運(yùn)行:

  1. go run main.go --app-path "Your project address" 

二、增加os.Getwd()進(jìn)行多層判斷

參見 beego 讀取 app.conf 的代碼。

該寫法可兼容 go build 和在項(xiàng)目根目錄執(zhí)行 go run ,但是若跨目錄執(zhí)行 go run 就不行。

三、配置全局系統(tǒng)變量

我們可以通過os.Getenv來獲取系統(tǒng)全局變量,然后與相對路徑進(jìn)行拼接。

1、 設(shè)置項(xiàng)目工作區(qū)

簡單來說,就是設(shè)置項(xiàng)目(應(yīng)用)的工作路徑,然后與配置文件、日志文件等相對路徑進(jìn)行拼接,達(dá)到相對的絕對路徑來保證路徑一致。

參見 gogs 讀取GOGS_WORK_DIR進(jìn)行拼接的代碼。

2、 利用系統(tǒng)自帶變量

簡單來說就是通過系統(tǒng)自帶的全局變量,例如$HOME等,將配置文件存放在$HOME/conf或/etc/conf下。

這樣子就能更加固定的存放配置文件,不需要額外去設(shè)置一個(gè)環(huán)境變量。

拓展

go test 在一些場景下也會(huì)遇到路徑問題,因?yàn)間o test只能夠在當(dāng)前目錄執(zhí)行,所以在執(zhí)行測試用例的時(shí)候,你的執(zhí)行目錄已經(jīng)是測試目錄了。

需要注意的是,如果采用獲取外部參數(shù)的辦法,用 os.args 時(shí),go test -args 和 go run、go build 會(huì)有命令行參數(shù)位置的不一致問題。

總結(jié)

這三種解決方案,在目前可見的開源項(xiàng)目或介紹中都能找到這些的身影。優(yōu)缺點(diǎn)也是顯而易見的,我認(rèn)為應(yīng)在不同項(xiàng)目選定合適的解決方案即可。

建議大家不要強(qiáng)依賴讀取配置文件的模塊,應(yīng)當(dāng)將其“堆積木”化,需要什么配置才去注冊什么配置變量,可以解決一部分的問題。

大家又有什么想法呢,一起討論一波?

 

責(zé)任編輯:武曉燕 來源: 腦子進(jìn)煎魚了
相關(guān)推薦

2011-07-11 13:29:03

JAVA

2020-04-24 09:53:59

Go協(xié)作搶占

2021-04-15 12:10:42

Go語言Go開發(fā)者

2010-03-18 08:48:30

Python入門

2021-07-29 20:28:24

靜態(tài)代碼Hdfs

2010-06-23 17:26:01

2017-12-26 10:19:14

大數(shù)據(jù)問題缺陷

2017-06-29 13:22:15

2011-06-23 15:33:24

SEO

2009-08-07 13:38:18

C#文件相對路徑

2023-07-06 13:56:14

微軟Skype

2020-09-08 06:54:29

Java Gradle語言

2009-08-06 18:31:57

C#相對路徑絕對路徑

2009-08-06 18:03:21

C#相對路徑

2023-09-22 17:36:37

2021-01-28 22:31:33

分組密碼算法

2020-05-22 08:16:07

PONGPONXG-PON

2018-06-07 13:17:12

契約測試單元測試API測試

2023-03-03 12:37:50

JavaJVM內(nèi)存溢出

2022-12-14 10:43:16

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91精品国产一区二区三区 | 亚洲 欧美 在线 一区 | 欧美男人亚洲天堂 | 亚洲综合一区二区三区 | 久久久久网站 | 国产在线观看一区 | 亚洲免费在线观看 | 91高清在线视频 | 精品成人av | 宅男伊人| 亚洲精品国产第一综合99久久 | 成人美女免费网站视频 | 国产一级在线 | 国产露脸国语对白在线 | 中文字幕亚洲视频 | 亚洲视频一区二区三区四区 | 91精品久久久久久综合五月天 | 中文字幕成人免费视频 | 精品免费国产一区二区三区 | 亚洲一区久久 | 妞干网av | 国产精品一区二区三区久久久 | 色综合久久88色综合天天 | 欧美精品一区二区三区一线天视频 | 国产99视频精品免视看9 | 91久久精品国产91久久 | 视频在线一区二区 | www.久草.com| 成人午夜在线视频 | 日韩中文字幕视频 | 久久久精品一区二区三区 | 国产精品一区久久久 | 北条麻妃99精品青青久久主播 | 国产精品1区 | 久久精品一区二区三区四区 | 午夜爽爽爽男女免费观看 | 欧美成人精品一区二区男人看 | 亚洲精品久久视频 | 国产精品久久久久久久久久久久 | 干出白浆视频 | 亚洲一区二区三区免费在线观看 |