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
        }
    }