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

當(dāng)前位置:首頁(yè) > 科技  > 軟件

在Go編程中調(diào)用外部命令的幾種場(chǎng)景

來(lái)源: 責(zé)編: 時(shí)間:2024-01-10 09:36:04 250觀看
導(dǎo)讀在很多場(chǎng)合, 使用Go語(yǔ)言需要調(diào)用外部命令來(lái)完成一些特定的任務(wù), 例如: 使用Go語(yǔ)言調(diào)用Linux命令來(lái)獲取執(zhí)行的結(jié)果,又或者調(diào)用第三方程序執(zhí)行來(lái)完成額外的任務(wù)。在go的標(biāo)準(zhǔn)庫(kù)中, 專門(mén)提供了os/exec包來(lái)對(duì)調(diào)用外部程序

在很多場(chǎng)合, 使用Go語(yǔ)言需要調(diào)用外部命令來(lái)完成一些特定的任務(wù), 例如: 使用Go語(yǔ)言調(diào)用Linux命令來(lái)獲取執(zhí)行的結(jié)果,又或者調(diào)用第三方程序執(zhí)行來(lái)完成額外的任務(wù)。在go的標(biāo)準(zhǔn)庫(kù)中, 專門(mén)提供了os/exec包來(lái)對(duì)調(diào)用外部程序提供支持, 本文將對(duì)調(diào)用外部命令常用的幾種場(chǎng)景進(jìn)行總結(jié)。yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

直接調(diào)用函數(shù)

先用Linux上的一個(gè)簡(jiǎn)單命令執(zhí)行看一下效果, 執(zhí)行cal命令, 會(huì)打印當(dāng)前月的日期信息,如圖:yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

如果要使用Go代碼調(diào)用該命令, 可以使用以下代碼:yak28資訊網(wǎng)——每日最新資訊28at.com

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

首先, 調(diào)用"os/exec"包中的Command函數(shù),并傳入命令名稱作為參數(shù), Command函數(shù)會(huì)返回一個(gè)exec.Cmd的命令對(duì)象。接著調(diào)用該命令對(duì)象的Run()方法運(yùn)行命令。yak28資訊網(wǎng)——每日最新資訊28at.com

如果此時(shí)運(yùn)行程序, 會(huì)發(fā)現(xiàn)什么都沒(méi)有出現(xiàn), 這是因?yàn)槲覀儧](méi)有處理標(biāo)準(zhǔn)輸出, 調(diào)用os/exec執(zhí)行命令, 標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤默認(rèn)會(huì)被丟棄。yak28資訊網(wǎng)——每日最新資訊28at.com

這里將cmd結(jié)構(gòu)中的Stdout和Stderr分別設(shè)置為os.stdout和os.Stderr, 代碼如下:yak28資訊網(wǎng)——每日最新資訊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())    }}

運(yùn)行程序后顯示:yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

輸出到文件

輸出到文件的關(guān)鍵, 是將exec.Cmd對(duì)象的Stdout和Stderr賦值文件句柄, 代碼如下:yak28資訊網(wǎng)——每日最新資訊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打開(kāi)一個(gè)文件, 指定os.0_CREATE標(biāo)志讓操作系統(tǒng)在文件不存在時(shí)自動(dòng)創(chuàng)建, 返回文件對(duì)象*os.File, *os.File實(shí)現(xiàn)了io.Writer接口。yak28資訊網(wǎng)——每日最新資訊28at.com

運(yùn)行程序結(jié)果如下:yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

發(fā)送到網(wǎng)絡(luò)

這里開(kāi)啟一個(gè)HTTP服務(wù), 服務(wù)端接收兩個(gè)參數(shù):年和月, 在服務(wù)端通過(guò)執(zhí)行系統(tǒng)命令返回結(jié)果,代碼如下:yak28資訊網(wǎng)——每日最新資訊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)}

打開(kāi)瀏覽器,在地址欄中輸入U(xiǎn)RL查詢2023年10月份的日歷:http://localhost:8001/querydate?year=2023&mnotallow=10 , 結(jié)果如下:yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

輸出到多個(gè)目標(biāo)

如果要將執(zhí)行命令的結(jié)果同時(shí)輸出到文件、網(wǎng)絡(luò)和內(nèi)存對(duì)象, 可以使用io.MultiWriter滿足需求, io.MultiWriter可以很方便的將多個(gè)io.Writer轉(zhuǎn)換成一個(gè)io.Writer, 修改之前的Web服務(wù)端程序如下:yak28資訊網(wǎng)——每日最新資訊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)}

分別獲取輸出內(nèi)容和錯(cuò)誤

這里我們封裝一個(gè)常用函數(shù), 輸入接收命令和多個(gè)參數(shù), 返回錯(cuò)誤和命令返回信息, 函數(shù)代碼如下:yak28資訊網(wǎng)——每日最新資訊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()}

該函數(shù)可以作為通用的命令執(zhí)行返回結(jié)果的函數(shù), 分別返回了錯(cuò)誤和命令返回信息。yak28資訊網(wǎng)——每日最新資訊28at.com

循環(huán)獲取命令內(nèi)容

在Linux系統(tǒng)中,有些命令運(yùn)行后結(jié)果是動(dòng)態(tài)持續(xù)更新的,例如: top命令,對(duì)于該場(chǎng)景,我們封裝函數(shù)如下:yak28資訊網(wǎng)——每日最新資訊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}

通過(guò)調(diào)用cmd對(duì)象的StdoutPipe()輸出管理函數(shù), 我們可以實(shí)現(xiàn)持續(xù)獲取后臺(tái)命令返回的結(jié)果,并保持程序不退出。yak28資訊網(wǎng)——每日最新資訊28at.com

在調(diào)用該函數(shù)的時(shí)候, 調(diào)用方式如下:yak28資訊網(wǎng)——每日最新資訊28at.com

<-ExecCommandLoopTimeOutput("top")

打印出的信息將是一個(gè)持續(xù)顯示信息,如圖:yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

總結(jié)

本章節(jié)介紹了使用os/exec這個(gè)標(biāo)準(zhǔn)庫(kù)調(diào)用外部命令的各種場(chǎng)景。在實(shí)際應(yīng)用中, 基本用的最多的還是封裝好的:ExecCommandOneTimeOutput()和ExecCommandLoopTimeOutput()兩個(gè)函數(shù), 畢竟外部命令一般只會(huì)包含兩種:一種是執(zhí)行后馬上獲取結(jié)果,第二種就是常駐內(nèi)存持續(xù)獲取結(jié)果。yak28資訊網(wǎng)——每日最新資訊28at.com

yak28資訊網(wǎng)——每日最新資訊28at.com

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

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 全網(wǎng)最詳細(xì)MVCC講解,一篇看懂

下一篇: Rust真慢,差點(diǎn)跟同事打起來(lái)

標(biāo)簽:
  • 熱門(mén)焦點(diǎn)
Top 主站蜘蛛池模板: 保定市| 沂南县| 清新县| 伊宁市| 夏津县| 朝阳县| 长岛县| 青铜峡市| 德格县| 建昌县| 保德县| 临高县| 林口县| 志丹县| 依安县| 岳阳市| 五指山市| 奇台县| 琼结县| 肥乡县| 丽水市| 连城县| 平邑县| 繁峙县| 西藏| 临夏县| 江达县| 炎陵县| 桃源县| 白山市| 西藏| 遂溪县| 珲春市| 高邑县| 隆昌县| 博罗县| 梁河县| 宁津县| 芦山县| 奈曼旗| 宁陕县|