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