精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

go語言底層對于命令行參數的解析

冬至子 ? 來源:我的小碗湯 ? 作者:小碗湯 ? 2022-10-11 10:50 ? 次閱讀

前段時間有群友在群里問一個go語言的問題:

就是有一個main.go的main函數里調用了另一個demo.go里的hello()函數。其中main.go和hello.go同屬于main包。但是在main.go的目錄下執行go run main.go卻報hello函數沒有定義的錯:

pYYBAGNE2XiAbE_6AABJdSb2xQ0407.png

代碼結構如下:

**gopath ---- src**

          **----gohello** 

                **----hello.go** 

                    **----main.go**

main.go如下:

package main

import "fmt"

func main() {

 fmt.Println("my name is main")

 hello()
}

hello.go如下:

package main

import "fmt"

func hello() {
 fmt.Println("my name is hello")
}

當時我看了以為是他GOPATH配置的有問題,然后自己也按照這樣試了一下,報同樣的錯,在網上查了,也有兩篇文章是關于這個錯的,也提供了解決方法,即用go run main.go hello.go,試了確實是可以的。

poYBAGNE2YqAUSTjAAA_Q8R_NUQ625.png

雖然是個很簡單的問題,但是也涉及到了go語言底層對于命令行參數的解析。那就來分析一下語言底層的實現吧,看一下底層做了什么,為什么報這個錯?

分析:

以下使用到的Go SDK版本為1.8.3

該版本中go支持的基本命令有以下16個:

build       compile packages and dependencies
clean       remove object files
doc         show documentation for package or symbol
env         print Go environment information
bug         start a bug report
fix         run go tool fix on packages
fmt         run gofmt on package sources
generate    generate Go files by processing source
get         download and install packages and dependencies
install     compile and install packages and dependencies
list        list packages
run         compile and run Go program
test        test packages
tool        run specified go tool
version     print Go version
vet         run go tool vet on packages

在Go SDK的src/cmd/go包下有main.go文件中,Command類型的commands數組對該16個命令提供了支持:

poYBAGNE2aGAGmHEAADVufp8n54966.png

我們首先知道go語言的初始化流程如下:

pYYBAGNE2bWAP7QzAABkuYqe9Uw995.png

在執行main.go中的主函數main之前,對import進來的包按順序初始化,最后初始化main.go中的類型和變量,當初始化到commands數組時,由于cmdRun定義在于main.go同包下的run.go中,那么就先去初始化run.go中的變量和init方法,如下代碼,先把cmdRun初始化為Command類型,然后執行init()函數。

var cmdRun = &Command{
 UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
 Short:     "compile and run Go program",
 Long: `
Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.

By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
If the -exec flag is given, 'go run' invokes the binary using xprog:
 'xprog a.out arguments...'.
If the -exec flag is not given, GOOS or GOARCH is different from the system
default, and a program named go_$GOOS_$GOARCH_exec can be found
on the current search path, 'go run' invokes the binary using that program,
for example 'go_nacl_386_exec a.out arguments...'. This allows execution of
cross-compiled programs when a simulator or other execution method is
available.

For more about build flags, see 'go help build'.

See also: go build.
 `,
}

func init() {
 cmdRun.Run = runRun // break init loop

 addBuildFlags(cmdRun)
 cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "")
}

init()中,將runRun(其實類型是一個方法,用于處理run后的參數)賦值給cmdRu.run,addBuildFlags(cmdRun)主要是給run后面增加命令行參數(如:-x是打印其執行過程中用到的所有命令,同時執行它們)。其他15個命令和cmdRun類似,各有各的run實現。

下來主要看main.go中main的這塊代碼:

for _, cmd := range commands {
   if cmd.Name() == args[0] && cmd.Runnable() {
     cmd.Flag.Usage = func() { cmd.Usage() }
     if cmd.CustomFlags {
       args = args[1:]
     } else {
       cmd.Flag.Parse(args[1:])
       args = cmd.Flag.Args()
     }
     cmd.Run(cmd, args)
     exit()
     return
   }
 }

這塊代碼遍歷commands數組,當遍歷到cmdRun時,cmd.Name()其實就是拿到cmdRun.UsageLine的第一個單詞run

bVeVF


就會進入if分支,由于cmd.CustomFlags沒有初始化故為false,走else分支,然后開始解析args命令行參數,args[1:]即取run后的所有參數。然后去執行cmd.Run(cmd, args),對于cmdRun來說,這里執行的就是run.go中init()的第一行賦值cmdRun.run(上面說了,這是一個函數,不同命令實現方式不同),即去執行run.go中的runRun函數,該函數主要是將命令行參數當文件去處理,如果是_test為后綴的,即測試文件,直接報錯。如果是目錄也直接報錯(而且go run后面只能包含一個含main函數的go文件)。注意到有這么一行:

p := goFilesPackage(files)

goFilesPackage(files)除了校驗文件類型和后綴,還會入棧,加載,出棧等操作,由于啟動的時候沒有傳遞hello.go,所以系統加載main.go時找不到hello函數,導致報錯。




審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • main
    +關注

    關注

    0

    文章

    38

    瀏覽量

    6140
  • go語言
    +關注

    關注

    1

    文章

    158

    瀏覽量

    9029
收藏 人收藏

    評論

    相關推薦

    Shell腳本命令行解析

    Shell腳本解析命令行參數——Argparse(填坑)
    發表于 04-03 11:34

    cmd網絡經典命令行

    cmd網絡經典命令行:
    發表于 06-11 15:17 ?36次下載
    cmd網絡經典<b class='flag-5'>命令行</b>

    C語言入門教程-命令行參數

    命令行參數 在C中,獲取用戶輸入的命令行參數是很方便的。程序的主函數會接受一個argv參數。有許多高級的庫函數都會用到argv結構,所以了
    發表于 07-29 14:22 ?2604次閱讀

    caxa命令行中的應用

    caxa命令行中的應用 命令行對于大多用戶來說往往只是輸入數據的作用,但是其中的奧妙還有很多,下面就給大家
    發表于 10-18 18:18 ?2281次閱讀

    博達環網配置命令行

    博達工業交換要環網配置命令行
    發表于 12-27 16:24 ?0次下載

    CMD的命令行高級教程

    CMD的命令行高級教程
    發表于 10-24 08:31 ?30次下載
    CMD的<b class='flag-5'>命令行</b>高級教程

    自己動手實現命令行解析

    一、介紹嵌入式里面經常會自己做命令行,這里分享一個命令解析器代碼實現二、代碼實現mycmd.c
    發表于 12-22 18:51 ?13次下載
    自己動手實現<b class='flag-5'>命令行</b><b class='flag-5'>解析</b>器

    如何從命令行獲取和解析參數

    這是一篇技術干貨快文,能夠快速閱讀完。文章內容是關于如何從命令行獲取和解析參數,包括SystemVerilog本身支持的系統函數和UVM提供的函數封裝,并給出示例代碼和仿真結果。
    的頭像 發表于 05-30 14:05 ?2813次閱讀

    uvm命令行傳遞參數的小技巧

    當我們在創建動態仿真case時,使用命令行參數可以非常方便地控制DUT和TB的行為,比如配置寄存器、控制激勵的發送數量、打開或關閉某些scoreboard等。
    的頭像 發表于 08-19 11:53 ?5457次閱讀

    Shell命令行解釋器簡介

    Shell 是一個命令行解釋器,Shell 為用戶提供了與設備進行命令行交互的方式,用戶通過串口、以太網、無線等方式將命令傳輸給具有 Shell 功能的設備,設備會解析
    的頭像 發表于 08-19 17:20 ?3181次閱讀

    Golang基于flag庫實現一個命令行工具

    Golang 標準庫中的 flag 庫提供了解析命令行選項的能力,我們可以基于此來開發命令行工具。
    的頭像 發表于 10-28 09:26 ?1266次閱讀

    Linux命令行與shell腳本編寫

    Linux命令行與shell腳本編寫
    發表于 01-11 16:50 ?4次下載

    介紹Go里面經常使用到的命令行工具

    優秀的工具配合熟練的使用,往往可以讓開發效率大幅度提升,本小節介紹 Go 里面經常使用到的命令行工具。
    的頭像 發表于 05-22 16:58 ?1260次閱讀
    介紹<b class='flag-5'>Go</b>里面經常使用到的<b class='flag-5'>命令行</b>工具

    linux切換到命令行模式

    在Linux中,可以通過以下步驟切換到命令行模式: 打開終端。可以在應用菜單中找到終端或命令行終端。 在終端中輸入命令“exit”或“logout”,然后按回車鍵。 系統會提示您輸入管理員密碼。輸入
    的頭像 發表于 11-13 16:47 ?1721次閱讀

    idea如何輸入命令行參數

    在許多軟件開發和系統管理的任務中,我們經常需要向應用程序傳遞命令行參數命令行參數是在運行時傳遞給程序的值,用于指定程序的行為和配置選項。本文將詳細介紹如何在不同的編程
    的頭像 發表于 12-06 15:01 ?1082次閱讀