LINUX.ORG.RU

История изменений

Исправление kaldeon, (текущая версия) :

package main

func mkchan[T any](arr []T) <-chan T {
	ch := make(chan T)

	go func() {
		defer close(ch)
		for _, n := range arr {
			ch <- n
		}
	}()

	return ch
}

func sendout[T any](input <-chan T, cond func(v T) bool) (<-chan T, <-chan T) {
	var (
		west = make(chan T)
		east = make(chan T)
	)

	var westclosed, eastclosed bool

	go func() {
		var (
			westread = make(chan bool)
			eastread = make(chan bool)
		)
		defer close(westread)
		defer close(eastread)

		var nwest, neast int

		for n := range input {
			if cond(n) {
				nwest++
				go func() {
					west <- n
					westread <- true
				}()
			} else {
				neast++
				go func() {
					east <- n
					eastread <- true
				}()
			}
		}

		for nwest != 0 || neast != 0 {
			select {
			case <-westread:
				nwest--
			case <-eastread:
				neast--
			}
			if nwest == 0 && !westclosed {
				westclosed = true
				close(west)
			}
			if neast == 0 && !eastclosed {
				eastclosed = true
				close(east)
			}
		}
	}()

	return west, east
}

func main() {
	arr := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	cond := func(n int) bool { return n%2 == 0 }

	west, east := sendout(mkchan(arr), cond)
	for n := range west {
		println(n)
	}
	for n := range east {
		println(n)
	}
}

Исходная версия kaldeon, :

package main

func mkchan[T any](arr []T) <-chan T {
	ch := make(chan T)

	go func() {
		defer close(ch)
		for _, n := range arr {
			ch <- n
		}
	}()

	return ch
}

func sendout[T any](input <-chan T, cond func(v T) bool) (<-chan T, <-chan T) {
	var (
		west  = make(chan T)
		east = make(chan T)
	)

	var westclosed, eastclosed bool

	go func() {
		var (
			westread  = make(chan bool)
			eastread = make(chan bool)
		)
		defer close(westread)
		defer close(eastread)

		var nwest, neast int

		for n := range input {
			if cond(n) {
				nwest++
				go func() {
					west <- n
					westread <- true
				}()
			} else {
				neast++
				go func() {
					east <- n
					eastread <- true
				}()
			}
		}

		for nwest != 0 || neast != 0 {
			select {
			case <-westread:
				nwest--
			case <-eastread:
				neast--
			}
			if nwest == 0 && !westclosed {
				westclosed = true
				close(west)
			}
			if neast == 0 && !eastclosed {
				eastclosed = true
				close(east)
			}
		}
	}()

	return west, east
}

func main() {
	arr := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	cond := func(n int) bool { return n%2 == 0 }

	west, east := sendout(mkchan(arr), cond)
	for n := range west {
		println(n)
	}
	for n := range east {
		println(n)
	}
}