Golangコンカレントモード--channelの高度な使用
17897 ワード
or-done channel
再pipelineの場合、goroutine終了をdone
で通知します.しかしながら、我々が処理したchannelがシステムの他の分散した部分から来た場合、done
によって制御することはできない.なぜなら、データストリームが終了する時間が分からないため、or-done
メカニズムを導入する必要があるからである.or-done
メカニズムは本質的に外部データchannelのパッケージであり、実際に制御することができる.
コードの例を示します.package main
func main() {
orDone := func(done, c chan interface{}) chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
select {
case done:
return
case v, ok := c:
if ok == false { //
return
}
select { //
case valStream v:
case done:
}
}
}
}()
return valStream
}
}
tee-channel
teeはlinuxのtee
コマンドに由来し、このモードの核心的な役割は、送信されたデータストリームをコードの2つの異なる場所に再送信することである.channel
を渡し、同じ値を得るために2つの個別のchannel
を返します.コードの例を示します.package main
import "fmt"
func main() {
tee := func(done chan interface{}, in chan interface{}) (chan interface{}, chan interface{}) {
out1 := make(chan interface{})
out2 := make(chan interface{})
go func() {
defer close(out1)
defer close(out2)
for val := range in {
var out1, out2 = out1, out2 //
for i := 0; i < 2; i++ {
select {
case done:
return
case out1 val:
out1 = nil // select
case out2 val:
out2 = nil
}
}
}
}()
return out1, out2
}
genetor := func(done chan interface{}, n int) chan interface{} {
genCh := make(chan interface{})
go func() {
defer close(genCh)
for i := 0; i < n; i++ {
select {
case done:
return
case genCh i:
}
}
}()
return genCh
}
done := make(chan interface{})
defer close(done)
out1, out2 := tee(done, genetor(done, 10))
for val1 := range out1 {
val2 := out2
fmt.Printf("%v, %v
", val1, val2)
}
}
ブリッジチャネル
セクタアウトモードでは、入力に秩序は必要ありません.ブリッジchannelはこれとは正反対で,このモードは入力秩序の場合に適用され,複数のデータストリームの入力は秩序ある取得を必要とする.私たちはまず1つのchannelのデータを処理してから、下へ処理を続ける必要があります.このとき、この複数の入力されたchannelを集合としてchannelに単独で配置することができます.
コードの例を示します.package main
func main() {
bridge := func(done chan interface{}, chanStream chan chan interface{}) chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
var stream chan interface{}
select {
case maybeStream, ok := chanStream:
if ok == false { // channel ,
return
}
stream = maybeStream
case done:
return
}
// orDone , channel
for val := range orDone(done, stream) {
select {
case valStream val:
case done:
}
}
}
}()
return valStream
}
}
package main
func main() {
orDone := func(done, c chan interface{}) chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
select {
case done:
return
case v, ok := c:
if ok == false { //
return
}
select { //
case valStream v:
case done:
}
}
}
}()
return valStream
}
}
teeはlinuxの
tee
コマンドに由来し、このモードの核心的な役割は、送信されたデータストリームをコードの2つの異なる場所に再送信することである.channel
を渡し、同じ値を得るために2つの個別のchannel
を返します.コードの例を示します.package main
import "fmt"
func main() {
tee := func(done chan interface{}, in chan interface{}) (chan interface{}, chan interface{}) {
out1 := make(chan interface{})
out2 := make(chan interface{})
go func() {
defer close(out1)
defer close(out2)
for val := range in {
var out1, out2 = out1, out2 //
for i := 0; i < 2; i++ {
select {
case done:
return
case out1 val:
out1 = nil // select
case out2 val:
out2 = nil
}
}
}
}()
return out1, out2
}
genetor := func(done chan interface{}, n int) chan interface{} {
genCh := make(chan interface{})
go func() {
defer close(genCh)
for i := 0; i < n; i++ {
select {
case done:
return
case genCh i:
}
}
}()
return genCh
}
done := make(chan interface{})
defer close(done)
out1, out2 := tee(done, genetor(done, 10))
for val1 := range out1 {
val2 := out2
fmt.Printf("%v, %v
", val1, val2)
}
}
ブリッジチャネル
セクタアウトモードでは、入力に秩序は必要ありません.ブリッジchannelはこれとは正反対で,このモードは入力秩序の場合に適用され,複数のデータストリームの入力は秩序ある取得を必要とする.私たちはまず1つのchannelのデータを処理してから、下へ処理を続ける必要があります.このとき、この複数の入力されたchannelを集合としてchannelに単独で配置することができます.
コードの例を示します.package main
func main() {
bridge := func(done chan interface{}, chanStream chan chan interface{}) chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
var stream chan interface{}
select {
case maybeStream, ok := chanStream:
if ok == false { // channel ,
return
}
stream = maybeStream
case done:
return
}
// orDone , channel
for val := range orDone(done, stream) {
select {
case valStream val:
case done:
}
}
}
}()
return valStream
}
}
package main
func main() {
bridge := func(done chan interface{}, chanStream chan chan interface{}) chan interface{} {
valStream := make(chan interface{})
go func() {
defer close(valStream)
for {
var stream chan interface{}
select {
case maybeStream, ok := chanStream:
if ok == false { // channel ,
return
}
stream = maybeStream
case done:
return
}
// orDone , channel
for val := range orDone(done, stream) {
select {
case valStream val:
case done:
}
}
}
}()
return valStream
}
}