初學go,求指教
自己實現了一個,然后看了下老師的視頻,發現實現方式完全不一樣。
不知道老師有沒時間看下我這個例子,指導下有啥優缺點。
另外看完了老師關于goroutine的系列課程,收獲很多,感謝感謝
package main
import (
"fmt"
"time"
"sync"
)
//材料結構體
type data struct {
uid int //區分每個材料,便于打印展示
id int //區分每種材料,便于打印展示
time int //清洗耗時
}
var wg sync.WaitGroup
//每種材料個數
// var count int = rand.Intn(10) + 1
var count int = 5
var chanA = make(chan data, count*3)
var chanB = make(chan data, count)
var chanC = make(chan data, count)
//獲取當前毫秒級時間
func now() int64 {
return (int64)(time.Now().UnixNano() / 1000 / 1000)
}
//清理材料
func A(id int) {
for {
select {
case d := <- chanA :?
fmt.Printf("time:%d A車工人:%d,材料%d:%d 清洗中...\n", now(), id, d.id, d.uid)
time.Sleep((time.Duration)(d.time * 100) * time.Millisecond)
fmt.Printf("time:%d A車工人:%d,材料%d:%d 清洗完成\n", now(), id, d.id, d.uid)
//清理完成,放入加工管道
chanB <- d
default :
break
}
}
}
//加工材料
func B(id int) {
cnt := 0
for {
select {
case d := <- chanB :?
fmt.Printf("time:%d B車工人:%d,材料%d:%d 加工中...\n", now(), id, d.id, d.uid)
time.Sleep(100 * time.Millisecond)
fmt.Printf("time:%d B車工人:%d,材料%d:%d 加工完成\n", now(), id, d.id, d.uid)
//加工完成,放入裝載管道
chanC <- d
cnt += 1
default :
}
if cnt >= count {
break
}
}
}
//裝載材料
func C(id int) {
for {
select {
case d := <- chanC :?
fmt.Printf("time:%d C車工人:%d,材料%d:%d 裝載中...\n", now(), id, d.id, d.uid)
time.Sleep(100 * time.Millisecond)
fmt.Printf("time:%d C車工人:%d,材料%d:%d 裝載完成\n", now(), id, d.id, d.uid)
//清理完成,放入裝載管道
wg.Done()
default :
}
}
}
func main() {
fmt.Println("demo start")
//聲明3種材料需要的空間
var list []data = make([]data, count*3)
var d data
//填充3種材料的數據
for i := 0; i < count; i++ {
//填充第一種材料數據,清洗耗時6
d = data{uid : i, id : 1, time : 6}
list[i] = d
//填充第二種材料數據,清洗耗時3
d = data{uid : i, id : 2, time : 3}
list[i + count] = d
//填充第二種材料數據,清洗耗時3
d = data{uid : i, id : 3, time : 3}
list[i + count * 2] = d
}
//往清洗的管道按清洗時間長短填充
for i := 0; i < len(list); i++ {
chanA <- list[i]
}
//A車3個清洗工人
go A(1)
go A(2)
go A(3)
//B車3個加工工人
go B(1)
go B(2)
go B(3)
//C車3個裝載工人
go C(1)
go C(2)
go C(3)
wg.Add(count*3)
wg.Wait()
fmt.Println("demo end")
}
2022-01-11
package?main import?( ???"fmt" ???"sync" ???"time" ) var?global?=?sync.WaitGroup{} //?A車傳送給B車的通道 var?ch1?=?make(chan?*material,?3) //?B車傳送給C車的通道 var?ch2?=?make(chan?*material,?3) //?食材 type?material?struct?{ ???//?食材名稱 ???name?string ???//?食材數量 ???count?byte ???//?A車處理所需花費時間,單位秒 ???elapsedTimeA?uint ???//?B車處理所需花費時間,單位秒 ???elapsedTimeB?uint ???//?C車處理所需花費時間,單位秒 ???elapsedTimeC?uint } func?main()?{ ???global.Add(3) ???//?所有需要處理的食材 ???materials?:=?[]*material{ ??????{"白菜",?12,?2,?1,?1}, ??????{"青菜",?12,?1,?1,?1}, ??????{"胡蘿卜",?12,?1,?1,?1}, ???} ???start?:=?time.Now() ???go?A(materials) ???go?B() ???go?C() ???global.Wait() ???cost?:=?time.Since(start) ???fmt.Printf("總耗時:%s\n",?cost) } func?A(materials?[]*material)?{ ???fmt.Printf("A車出發\n") ???//?循環處理每種食材 ???for?_,?ele?:=?range?materials?{ ??????var?worker?=?sync.WaitGroup{} ??????worker.Add(3) ??????//?3名工人分別處理每種食材的1/3 ??????for?i?:=?0;?i?<?3;?i++?{ ?????????go?func(index?int,?ele2?*material)?{ ????????????fmt.Printf("A車工人[%d]正在清洗食材[%s],數量[%d],預計耗時[%d]秒\n",?index,?ele2.name,?ele2.count/3,?ele2.elapsedTimeA) ????????????//?睡眠模擬處理食材耗時 ????????????time.Sleep(time.Second?*?time.Duration(ele2.elapsedTimeA)) ????????????worker.Done() ?????????}(i,?ele) ??????} ??????//?等待所有工人都處理完畢后,把處理后的食材傳送給B車 ??????worker.Wait() ??????fmt.Printf("A車食材[%s]正在運往B車\n",?ele.name) ??????ch1?<-?ele ???} ???fmt.Printf("A車任務結束\n") ???global.Done() } func?B()?{ ???fmt.Printf("B車出發\n") ???//?循環處理3種食材 ???for?i?:=?0;?i?<?3;?i++?{ ??????//?從通道取不到數據時會阻塞,只有通道關閉時ok才等于false,所以下面的if判斷可以忽略 ??????ele,?ok?:=?<-ch1 ??????if?!ok?{ ?????????break ??????} ??????fmt.Printf("B車接收到A車食材[%s]\n",?ele.name) ??????var?worker?=?sync.WaitGroup{} ??????worker.Add(3) ??????for?j?:=?0;?j?<?3;?j++?{ ?????????go?func(index?int,?ele2?*material)?{ ????????????fmt.Printf("B車工人[%d]正在加工食材[%s],數量[%d],預計耗時[%d]秒\n",?index,?ele2.name,?ele2.count/3,?ele2.elapsedTimeB) ????????????//?睡眠模擬處理食材耗時 ????????????time.Sleep(time.Second?*?time.Duration(ele2.elapsedTimeB)) ????????????worker.Done() ?????????}(j,?ele) ??????} ??????//?等待所有工人都處理完畢后,把處理后的食材傳送給C車 ??????worker.Wait() ??????fmt.Printf("B車食材[%s]正在運往C車\n",?ele.name) ??????ch2?<-?ele ???} ???fmt.Printf("B車任務結束\n") ???global.Done() } func?C()?{ ???fmt.Printf("C車出發\n") ???for?i?:=?0;?i?<?3;?i++?{ ??????//?從通道取不到數據時會阻塞,只有通道關閉時ok才等于false,所以下面的if判斷可以忽略 ??????ele,?ok?:=?<-ch2 ??????if?!ok?{ ?????????break ??????} ??????fmt.Printf("C車接收到B車食材[%s]\n",?ele.name) ??????var?worker?=?sync.WaitGroup{} ??????worker.Add(3) ??????for?j?:=?0;?j?<?3;?j++?{ ?????????go?func(index?int,?ele2?*material)?{ ????????????fmt.Printf("C車工人[%d]正在裝載食材[%s],數量[%d],預計耗時[%d]秒\n",?index,?ele2.name,?ele2.count/3,?ele2.elapsedTimeC) ????????????//?睡眠模擬處理食材耗時 ????????????time.Sleep(time.Second?*?time.Duration(ele2.elapsedTimeC)) ????????????worker.Done() ?????????}(j,?ele) ??????} ??????worker.Wait() ???} ???fmt.Printf("C車任務結束\n") ???global.Done() }