日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

在Go編程中調用外部命令的幾種場景

來源: 責編: 時間:2024-01-10 09:36:04 227觀看
導讀在很多場合, 使用Go語言需要調用外部命令來完成一些特定的任務, 例如: 使用Go語言調用Linux命令來獲取執行的結果,又或者調用第三方程序執行來完成額外的任務。在go的標準庫中, 專門提供了os/exec包來對調用外部程序

在很多場合, 使用Go語言需要調用外部命令來完成一些特定的任務, 例如: 使用Go語言調用Linux命令來獲取執行的結果,又或者調用第三方程序執行來完成額外的任務。在go的標準庫中, 專門提供了os/exec包來對調用外部程序提供支持, 本文將對調用外部命令常用的幾種場景進行總結。7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

直接調用函數

先用Linux上的一個簡單命令執行看一下效果, 執行cal命令, 會打印當前月的日期信息,如圖:7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

如果要使用Go代碼調用該命令, 可以使用以下代碼:7tm28資訊網——每日最新資訊28at.com

func main(){  cmd := exec.Command("cal")  err := cmd.Run()  if err != nil {     fmt.Println(err.Error())  }}

首先, 調用"os/exec"包中的Command函數,并傳入命令名稱作為參數, Command函數會返回一個exec.Cmd的命令對象。接著調用該命令對象的Run()方法運行命令。7tm28資訊網——每日最新資訊28at.com

如果此時運行程序, 會發現什么都沒有出現, 這是因為我們沒有處理標準輸出, 調用os/exec執行命令, 標準輸出和標準錯誤默認會被丟棄。7tm28資訊網——每日最新資訊28at.com

這里將cmd結構中的Stdout和Stderr分別設置為os.stdout和os.Stderr, 代碼如下:7tm28資訊網——每日最新資訊28at.com

func main(){    cmd := exec.Command("cal")    cmd.Stdout = os.Stdout    cmd.Stderr = os.Stderr    err := cmd.Run()    if err != nil {      fmt.Println(err.Error())    }}

運行程序后顯示:7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

輸出到文件

輸出到文件的關鍵, 是將exec.Cmd對象的Stdout和Stderr賦值文件句柄, 代碼如下:7tm28資訊網——每日最新資訊28at.com

func main(){    f, err := os.OpenFile("sample.txt", os.O_WRONLY|os.O_CREATE, os.ModePerm)    if err != nil {      fmt.Println(err.Error())    }    cmd := exec.Command("cal")    cmd.Stdout = f    cmd.Stderr = f    err := cmd.Run()    if err != nil {      fmt.Println(err.Error())    }}

os.OpenFile打開一個文件, 指定os.0_CREATE標志讓操作系統在文件不存在時自動創建, 返回文件對象*os.File, *os.File實現了io.Writer接口。7tm28資訊網——每日最新資訊28at.com

運行程序結果如下:7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

發送到網絡

這里開啟一個HTTP服務, 服務端接收兩個參數:年和月, 在服務端通過執行系統命令返回結果,代碼如下:7tm28資訊網——每日最新資訊28at.com

import (  "fmt"  "net/http"  "os/exec")func queryDate(w http.ResponseWriter, r *http.Request) {  var err error  if r.Method == "GET" {    year := r.URL.Query().Get("year")    month := r.URL.Query().Get("month")    cmd := exec.Command("cal", month, year)    cmd.Stdout = w    cmd.Stderr = w    err = cmd.Run()    if err != nil {      fmt.Println(err.Error())    }  }}func main() {  http.HandleFunc("/querydate", queryDate)  http.ListenAndServe(":8001", nil)}

打開瀏覽器,在地址欄中輸入URL查詢2023年10月份的日歷:http://localhost:8001/querydate?year=2023&mnotallow=10 , 結果如下:7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

輸出到多個目標

如果要將執行命令的結果同時輸出到文件、網絡和內存對象, 可以使用io.MultiWriter滿足需求, io.MultiWriter可以很方便的將多個io.Writer轉換成一個io.Writer, 修改之前的Web服務端程序如下:7tm28資訊網——每日最新資訊28at.com

func queryDate(w http.ResponseWriter, r *http.Request) {  var err error  if r.Method == "GET" {    buffer := bytes.NewBuffer(nil)    year := r.URL.Query().Get("year")    month := r.URL.Query().Get("month")    f, _ := os.OpenFile("sample.txt", os.O_WRONLY|os.O_CREATE, os.ModePerm)    mw := io.MultiWriter(w, f, buffer)    cmd := exec.Command("cal", month, year)    cmd.Stdout = mw    cmd.Stderr = mw    err = cmd.Run()    if err != nil {      fmt.Println(err.Error())    }    fmt.Println(buffer.String())  }}func main() {  http.HandleFunc("/querydate", queryDate)  http.ListenAndServe(":8001", nil)}

分別獲取輸出內容和錯誤

這里我們封裝一個常用函數, 輸入接收命令和多個參數, 返回錯誤和命令返回信息, 函數代碼如下:7tm28資訊網——每日最新資訊28at.com

func ExecCommandOneTimeOutput(name string, args ...string) (error, string) {  var out bytes.Buffer  var stderr bytes.Buffer  cmd := exec.Command(name, args...)  cmd.Stdout = &out  cmd.Stderr = &stderr  err := cmd.Run()  if err != nil {    fmt.Println(fmt.Sprint(err) + ": " + stderr.String())    return err, ""  }  return nil, out.String()}

該函數可以作為通用的命令執行返回結果的函數, 分別返回了錯誤和命令返回信息。7tm28資訊網——每日最新資訊28at.com

循環獲取命令內容

在Linux系統中,有些命令運行后結果是動態持續更新的,例如: top命令,對于該場景,我們封裝函數如下:7tm28資訊網——每日最新資訊28at.com

func ExecCommandLoopTimeOutput(name string, args ...string) <-chan struct{} {  cmd := exec.Command(name, args...)  closed := make(chan struct{})  defer close(closed)  stdoutPipe, err := cmd.StdoutPipe()  if err != nil {    fmt.Println(err.Error())  }  defer stdoutPipe.Close()  go func() {    scanner := bufio.NewScanner(stdoutPipe)    for scanner.Scan() {      fmt.Println(string(scanner.Bytes()))      _, err := simplifiedchinese.GB18030.NewDecoder().Bytes(scanner.Bytes())      if err != nil {        continue      }    }  }()  if err := cmd.Run(); err != nil {    fmt.Println(err.Error())  }  return closed}

通過調用cmd對象的StdoutPipe()輸出管理函數, 我們可以實現持續獲取后臺命令返回的結果,并保持程序不退出。7tm28資訊網——每日最新資訊28at.com

在調用該函數的時候, 調用方式如下:7tm28資訊網——每日最新資訊28at.com

<-ExecCommandLoopTimeOutput("top")

打印出的信息將是一個持續顯示信息,如圖:7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

總結

本章節介紹了使用os/exec這個標準庫調用外部命令的各種場景。在實際應用中, 基本用的最多的還是封裝好的:ExecCommandOneTimeOutput()和ExecCommandLoopTimeOutput()兩個函數, 畢竟外部命令一般只會包含兩種:一種是執行后馬上獲取結果,第二種就是常駐內存持續獲取結果。7tm28資訊網——每日最新資訊28at.com

7tm28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-59680-0.html在Go編程中調用外部命令的幾種場景

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 全網最詳細MVCC講解,一篇看懂

下一篇: Rust真慢,差點跟同事打起來

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 宣武区| 江阴市| 常州市| 玛曲县| 安乡县| 宁海县| 利津县| 天全县| 无极县| 永寿县| 奉节县| 黄石市| 湖北省| 麻阳| 青阳县| 夹江县| 德惠市| 海口市| 青海省| 法库县| 遂溪县| 富民县| 新沂市| 黑龙江省| 拜城县| 汾阳市| 金华市| 林州市| 厦门市| 平武县| 防城港市| 玉林市| 新晃| 博湖县| 甘谷县| 八宿县| 石首市| 承德市| 读书| 双峰县| 涿州市|