亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

老師,請問,為什么不能循環一次,open一次,讀完數據并存儲,close一次,再循環?我實驗過,確實失敗了

func?createPipeline(
???filename?string,
???fileSize,?chunkCount?int)??<-?chan?int{
???chunkSize?:=?fileSize/chunkCount

???sortResults?:=?[]?<-chan?int{}
???for?i:=?0;?i<?chunkCount;i++{

??????file,?err?:=?os.Open(filename)//每循環一次就open一次file
??????if?err?!=?nil{
?????????panic(err)
??????}

??????file.Seek(int64(i*chunkSize),0)

??????source?:=?zzpipeline.ReaderSource(
?????????bufio.NewReader(file),?chunkSize)

??????sortResults?=?append(sortResults,
?????????zzpipeline.InMemSort(source))
??????//此處在一次循環結束時,數據已經讀出并保存在sortResults中了,
??????//?為什么后面緊接著file.Close()會導致整個數據都讀不出來了呢?
??????file.Close()??//close與open都在循環體內

???}
???return?zzpipeline.MergeN(sortResults...)
}


正在回答

7 回答

11分45秒的時候老師解釋了,createPipeline只是創建了pipeline,也就是把一個文件分成了chunkCount個小快,各放上了一個channel,但是此時channel還是阻塞的,因為要等觸發了ReadSource以后才這些通道才會開始不斷傳輸。因此在CreatePipeline里面是不能file.close的,需要把這些file句柄返回出來,由外面close。老師說因為不想把這個示例搞的太復雜,所以就留下了這個坑。

2 回復 有任何疑惑可以回復我~

若要加bufio就要把open移到循環體里來

func createPipeline(filename string, fileSize ,

chunkSize int) ( <-chan int){

readSize := fileSize/chunkSize

pipeline.Init()

sources := [] <-chan int{}

for i := 0; i < chunkSize; i++ {

file, err := os.Open(filename)

if err != nil{

panic(err)

}

file.Seek(int64(i*readSize),0)

source := pipeline.ReadSource(bufio.NewReader(file), readSize)

sort := pipeline.InMemSort(source)

sources = append(sources, sort)

fmt.Printf("n:%d\n", i)

}

return pipeline.MergeN(sources...)

}


0 回復 有任何疑惑可以回復我~

func createPipeline(filename string, fileSize ,

chunkSize int) ( <-chan int, *os.File){

file, err := os.Open(filename)

if err != nil{

panic(err)

}

readSize := fileSize/chunkSize


sources := [] <-chan int{}

for i := 0; i < chunkSize; i++ {


source := pipeline.ReadSource(file, readSize)

sort := pipeline.InMemSort(source)

sources = append(sources, sort)

}


return pipeline.MergeN(sources...), file

} //這樣就把file傳出去close了,看了不點個贊嗎?


1 回復 有任何疑惑可以回復我~

這樣加defer 不可靠還體現在:若是在循環后sleep個幾秒鐘,最終處理到560m左右的數據,file就會被關閉。如果在循環體里打印的話,可以發現這4次循環瞬間就完成了。而數據還沒開始處理。所以不能在生產完管道后就立馬關閉file,必須等所有事情處理完才能file.Close()。所以不能在函數內關閉,要把[]*File傳到外面去關閉。

0 回復 有任何疑惑可以回復我~
defer?file.Close()并不可靠,它會運行一次只允許處理12k數據下一次處理8k數據,這樣交替。但我們有800M
的數據。所以只能把file傳到外面等事情做完之后,再close掉。
0 回復 有任何疑惑可以回復我~

這要從生命周期來考慮,這個函數只是生成pipeline,管道還沒開始運行,就把file關閉了,當然就取不出數據啊。

在一次循環結束時,數據并沒有讀出并保存在sortResults中?;仡^看看zzpipeline.ReaderSource就知道了,
?它也只是搭了個管道。但是貌似go的編譯器很聰明,改成defer?file.Close()是可以的。
0 回復 有任何疑惑可以回復我~

能想到的大概兩個原因:

  1. 每次都開關是有性能損耗的,打開和關閉需要耗時;但這個并不是關鍵的。

  2. 每次需要存儲讀到的位置,下次打開時,還要從上次的地方開始讀??;這會增加程序的復雜讀,這里跟數據庫的長連接情況方便查詢不一樣。? 打開一次足夠的。

0 回復 有任何疑惑可以回復我~

舉報

0/150
提交
取消

老師,請問,為什么不能循環一次,open一次,讀完數據并存儲,close一次,再循環?我實驗過,確實失敗了

我要回答 關注問題
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號