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