<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 GetoptGo 解析命令行參數(shù)工具

          聯(lián)合創(chuàng)作 · 2023-10-02 05:41

          Go GetOpt,讓你在 go 里解析命令行參數(shù)無聊地跟寫 shell 腳本一樣。


          為了不引起混淆,以下說明將使用

          go getopt 表示本代碼倉庫

          shell getopt、getopt 命令 表示 util-linux 中的 getopt 二進制程序

          getopt(或 C getopt)表示 libc 中的 getopt 方法

          但在某個上下文(如標題說明了該段是 shell getopt)中可能有時會直接使用 getopt 指代。請各位注意區(qū)分。


          怎么用

          go get gitee.com/go-getopt/go-getopt
          
          package main
          
          import (
              "fmt"
              "os"
          
              // 這里為了方便,直接使用 . 進行 import。
              // 這樣可以直接調(diào)用 GetOpt、Get 和 Shift 方法。
              . "gitee.com/go-getopt/go-getopt"
          )
          
          func main() {
              // 傳入 os.Args、options 和 longOptions 字符串參數(shù)即可
              err := GetOpt(os.Args, "ab:c::", "a-long,b-long:,c-long::")
              if err != nil {
                  fmt.Fprintln(os.Stderr, err)
                  os.Exit(1)
              }
          
              // 解析后的參數(shù)列表存儲在全局變量 Args 中
              fmt.Println("Arguments:", Args)
              fmt.Println("Program name:", Args[0])
          
              // 接下來的步驟就和 shell 差不多了
              for loop := true; loop; {
                  switch Get(1) {
                  case "-a", "--a-long":
                      fmt.Println("Option a")
                      Shift(1)
                  case "-b", "--b-long":
                      fmt.Println("Option b, argument '" + Get(2) + "'")
                      Shift(2)
                  case "-c", "--c-long":
                      if Get(2) == "" {
                          fmt.Println("Option c, no argument")
                      } else {
                          fmt.Println("Option c with arg '" + Get(2) + "'")
                      }
                      Shift(2)
                  case "--":
                      Shift(1)
                      loop = false
                  default:
                      fmt.Fprintln(os.Stderr, "Error: wrong argument '"+arg1+"'")
                      os.Exit(1)
                  }
              }
              fmt.Println("Remains:", Args[1:])
          }
          

          對比一下 shell getopt 解析命令行的腳本:

          # 檢查 getopt 命令是否正常運行
          getopt --test > /dev/null
          
          [ $? -ne 4 ] &&
              echo "Error: command 'getopt --test' failed in this environment." &&
              exit 1
          
          # 設(shè)定 options 和 longOptions,調(diào)用 getopt 命令
          options=ab:c::
          longOptions=a-long,b-long:,c-long::
          
          parsed=$(getopt --options=$options --longoptions=$longOptions --name "$0" -- "$@")
          
          [ $? -ne 0 ] &&
              echo "Error: failed to parse cmd arguments" &&
              exit 1
          
          eval "set -- $parsed"
          
          # 循環(huán)判斷是哪個 flag,處理完后 shift 掉
          while true; do
              case "$1" in
                  -a|--a-long)
                      echo 'Option a'
                      shift
                  ;;
                  -b|--b-long)
                      echo "Option b, argument '$2'"
                      shift 2
                  ;;
                  -c|--c-long)
                      [ -n "$2" ] && \\
                      echo "Option c, argument '$2'" || \\
                      echo 'Option c, no argument'
                      shift 2
                  --)
                      shift
                      break
                  *)
                      echo "Error: wrong argument '$1'"
                      exit 1
                      ;;
              esac
          done
          echo "Remains: $@"
          

          Go GetOpt 適合哪些人用

          如果你符合以下的一條或多條,可能這個庫會適合你:

          • 想用一個庫讓 go 程序解析命令行參數(shù)方便一點。
          • 只想解析出字符串形式參數(shù),然后自己做處理或轉(zhuǎn)換。
          • 不想讓類型斷言、類型轉(zhuǎn)換代碼到處亂飛,也不需要調(diào)用的庫提供 GetInt、MustGetInt 之類的方法。
          • 忘不了前任 習慣了寫 shell,想找個差不多的庫接盤
          • 不喜歡 flag、pflag 這種類型的解析方式(pflag 也很久沒維護了)。
          • 不想用 cobra 這種很繁瑣的庫。

          其他問題

          并發(fā)(協(xié)程)安全嗎?

          沒辦法做到,也沒必要。C 的 getoptgetopt_long 方法本身就不是并發(fā)安全的(用了全局變量 optind、optarg 來存儲中間狀態(tài))。

          而且,命令行應(yīng)該只需要解析一次就可以了吧。有必要多次解析嗎???

          支持哪些平臺?

          這個庫是用 cgo 包裝 libc 中的 getopt_long 方法實現(xiàn)的。原理和 shell getopt 命令行程序差不多。目前主流的 libc 都是支持的:

          • mingw / msvc Windows 系
          • glibc Debian 系、CentOS 系
          • musl Alpine
          • uclibc-ng BusyBox

          附:各 libc getopt 和 getopt_long 源碼地址

          musl

          https://git.musl-libc.org/cgit/musl/tree/src/misc/getopt.c

          https://git.musl-libc.org/cgit/musl/tree/src/misc/getopt_long.c

          glibc

          https://sourceware.org/git/?p=glibc.git;a=blob;f=posix/getopt.c;h=e9661c79faa8920253bc37747b193d1bdcb288ef;hb=HEAD

          https://sourceware.org/git/?p=glibc.git;a=blob;f=posix/getopt1.c;h=990eee1b64fe1ee03e8b22771d2e88d5bba3ac68;hb=HEAD

          uclibc-ng

          https://gogs.waldemar-brodkorb.de/oss/uclibc-ng/src/master/libc/unistd/getopt.c

          https://gogs.waldemar-brodkorb.de/oss/uclibc-ng/src/master/libc/unistd/getopt_long-simple.c

          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          編輯 分享
          舉報
          <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>
                  又大又长又粗 | 日韩中文在线观看视频 | 人妻无码第23页 | 黄片网站在线免费 | 精品国自产在线偷拍无码视频 |