我們通常在go代碼時,通常採用idea或者命令行的形式進行編譯和運行,這兩天我遇到一個非常困惑的問題,一直沒找到具體原因,已經做了快一年的go程序員,看見這個問題甚是臉疼。
問題描述
在開發代碼過程中,經常會因爲邏輯處理而對代碼進行分類,放進不同的文件裏面;像這樣,同一個包下的兩個文件,點擊idea的運行按鈕或者運行 go run main.go命令時,會報出如下錯誤,詳情見圖:
command-line-arguments
src/demo/main/main.go:4:2: undefined: demo
Compilation finished with exit code 2
但是輸入 go build,之後當前目錄下會生成一個二進制文件,執行後會發現輸出正確結果:
問題分析:
通過操作發現,輸入go run main.go會執行失敗,輸入go build,在運行二進制文件可以成功,然後開始分析go源代碼,找到執行命令的入口。
在源代碼的main函數中,我們發現從base.Commands的切片中獲取要執行的命令,然後和傳入的args一起執行cmd.Run(cmd, args)這個方法;
然後再回過頭看cmd.Run(cmd, args)這個函數,結果發現它只是定義了一種類型,具體實現這裏沒有指出;
緊接着回頭去看run包下的函數,會發現run.go在初始化的時候,會把改文件下的runRun()函數賦值給base.Command{}定義的對象CmdRun,結果會發現runRun函數的的參數類型和個數完全符合cmd.Run(cmd, args)這個函數類型,在go語言中,函數的參數類型和參數個數符合定義的函數類型,則說明改函數實現了定義函數(注:go語言中,函數與方法不同)
在runRun()函數中,會發現files和cmdArgs接收的是傳過來的文件列表,然後會通過GoFilesPackage(files),然後會入棧、加載、出棧等操作,由於啓動的時候傳遞的只是一個.go文件,並沒有傳遞demo.go,所以系統在加載main.go文件中並沒有找到demo.go文件中定義的變量,則在p := load.GoFilesPackage(files)這一行,開始出錯。
正確操作:
該出錯原因屬於go的多文件加載問題,採用go run命令執行的時候,需要把待加載的.go文件都包含到參數裏面,正確操作如下圖所示: