golang 調用第三方二進制bin文件,實現golang調用進程。

bin文件可以是C++生成,或其他語言生成,此處用的是C++生成的二進制文件

如果你想在go語言中通過讀取文件,實現進程間的通信,可以繼續看下去:

功能包括:

1:文件保存,讀取

2:exec中的Command命令使用

3:主協程中啓用兩個協程並等待結束的方法

 

1:功能:需要用go調用第三方bin文件,傳參進去,通過讀寫文件實現進程間的通信。

func (this *BaiduAudioClient) InvokeSdk() (map[string]map[string]interface{}, error) {

    defer func() {
        if err := recover(); err != nil {
            fmt.Println("invoke recover for panic")
        }
    }()

    var sdkpath string
    var errS error
    if sdkpath, errS = filepath.Abs(filepath.Dir(os.Args[0])); errS != nil {  //讀取bin文件所在的路徑,也就是go進程啓動的路徑
        fmt.Println("can't find current filepath")
    } else {
        sdkpath = sdkpath + "/audiosdk"
        //fmt.Println("dir:", sdkpath)
    }

    var fn string = "/dev/shm/sdkaudio/" + this.RequestId
//fmt.Println("filename:", fn)
    cmdC := exec.Command(sdkpath, fn) //調用sdkpath這個路徑下名稱爲audiosdk的bin文件
    cmdC.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} //通過這個設置爲後續kill掉該進程做準備
    cmdC.Run() //啓動該進程,該函數和Start的區別時,該函數會阻塞,等待進程執行完成。,而Start不會,Start需要Wait實現相同功能


    ret := make(map[string]map[string]interface{})
    text := make(map[string]interface{})
    var json_result string

    readfile, errF := os.Open(fn + ".txt")//讀取再調用的進程裏面生成的文件
    if errF != nil {
        fmt.Printf("Error: %s\n", errF)
    }
    defer readfile.Close()

  ////一行一行讀取文件,一下全部讀取用ReadAll

    readcontent:= bufio.NewReader(readfile)

   for {
        linecontent, _, errC := readcontent.ReadLine()
        if errC == io.EOF {
            break
        }
        if string(linecontent) != "" {
            goresult := string(linecontent)

            //輸出gotesult查看結果

/*
            var audio_result map[string]interface{}
            if err := json.Unmarshal([]byte(goresult), &audio_result); err != nil {
                fmt.Println("baidu sdk unmarshal failed")
                return nil, err
            }
            if feature, err := this.ExtractSdkFeatures(audio_result); err != nil {
                fmt.Println("extract sdk feature failed")
                return nil, err
            } else {
                if txt, txt_ok := feature["text"].(string); txt_ok {
                    json_result = json_result + txt
                }

*/
                //text["text"] = json_result
                //ret["baidu_audio_sdk"] = text
                //fmt.Println(fn)
                //fmt.Println("content", json_result)
                //fmt.Println("111111 ret:", ret)
                //return ret, nil
            }
        }
    }
    text["text"] = json_result
    ret["baidu_audio_sdk"] = text

    this.KillCmd(cmdC)

    //刪除生成的文件
    _, errN := os.Stat(fn)
    if !os.IsNotExist(errN) {
        delaudio := os.Remove(fn)
        deltxt := os.Remove(fn + ".txt")
        if delaudio != nil || deltxt != nil {
            fmt.Println("del err audio file:",delaudio)

            fmt.Println("del err txt:",deltxt)
        }
    }

    return ret, nil
}
 

//通過cmd命令,將啓動的進程kill掉,注意,這裏要手動kill掉,否則進程會一直在那裏,成爲殭屍進程,佔用資源

func (this *BaiduAudioClient) KillCmd(cmd *exec.Cmd) {
        for {
                if cmd.Process != nil {
                        syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
                        break
                }
                time.Sleep(time.Second * 10)
        }
}

 

//golang將內存內容寫入本地文件,讀取之前,判斷所要讀取的路徑是否存在,不存在的話,創建

func (this *BaiduAudioClient) WriteBlock(line []byte) error {

    if _, err := os.Stat("/dev/shm/sdkaudio/"); err != nil {
        if os.IsNotExist(err) {
            if merr := os.Mkdir("/dev/shm/sdkaudio/", os.ModePerm); merr != nil {
                return merr
            }
        }
    }

    filename := fmt.Sprintf("/dev/shm/sdkaudio/" + this.RequestId)
    _, err1 := os.Create(filename)
    if err1 != nil {
        return err1
    }
    err := ioutil.WriteFile(filename, line, 0644)
    if err != nil {
        os.RemoveAll(filename)
        return err
    }
    return nil
}
 

2:golang中起多個協程,並等待最後執行結果的代碼

下面是golang中同時啓動兩個線程的操作,並等待該兩個線程結束時的代碼:

func (this *AudioService) {

    ret := make(map[string]map[string]interface{})
    tmpmap := make(map[string]map[string]interface{})
    syncChan := make(chan map[string]map[string]interface{}, 2)
    var threadNum int = 1

//fmt.Println("organization:", request.GetOrganization())
//fmt.Println("RequestId:", request.GetRequestId())
    audioType := this.Conf.AuthorityAudio.GetAuthority(request.GetOrganization())

    if audioType != "" {
        if (strings.Contains(audioType, "audio") && (json_data["invokeType"] == "AUDIO")) || (strings.Contains(audioType, "stream") && (json_data["invokeType"] == "AUDIOSTREAM")) {

            //線程1
            go func(syncChan chan<- map[string]map[string]interface{}) {
                if curRet, err := this.InvokeBaiduSdk(audioRequest); err != nil {
                    syncChan <- tmpmap
                } else {
                    syncChan <- curRet
                }
            }(syncChan)
            threadNum = 2 //注意,該代碼寫在括號}外表,會有問題,所以一定要和線程起來時,這個值才能賦值爲2
        }

//fmt.Println("audioType:", audioType)
    }

//線程2

    go func(syncChan chan<- map[string]map[string]interface{}) {
        if curRet, err := this.InvokeBaidu(audioRequest); err != nil {
            syncChan <- tmpmap
        } else {
            syncChan <- curRet
        }
    }(syncChan)

    for i := 0; i < threadNum; i++ {
        cur := <-syncChan
//fmt.Println("i:", i)
        for key, val := range cur {
            ret[key] = val
        }
    }


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章