Channels can connect pipeline stages while each stage keeps a small, deterministic responsibility.

channel pipeline Start a producer goroutine, transform each value in the main goroutine, and join through channel close semantics.

Channel Pipeline

count
channel_pipeline.go
Replay: real traced execution (multi-file project)
package main

import "fmt"

func main() {
	var count = 3
	inputs := make(chan int)
	outputs := []int{}

	go func() {
		for value := 1; value <= count; value++ {
			inputs <- value
		}
		close(inputs)
	}()

	for value := range inputs {
		outputs = append(outputs, value*value)
	}

	total := 0
	for _, value := range outputs {
		total += value
	}

	fmt.Println("count=", count)
	fmt.Println("outputs=", outputs)
	fmt.Println("total=", total)
}
package main

import "fmt"

func main() {
	var count = 2
	inputs := make(chan int)
	outputs := []int{}

	go func() {
		for value := 1; value <= count; value++ {
			inputs <- value
		}
		close(inputs)
	}()

	for value := range inputs {
		outputs = append(outputs, value*value)
	}

	total := 0
	for _, value := range outputs {
		total += value
	}

	fmt.Println("count=", count)
	fmt.Println("outputs=", outputs)
	fmt.Println("total=", total)
}
package main

import "fmt"

func main() {
	var count = 4
	inputs := make(chan int)
	outputs := []int{}

	go func() {
		for value := 1; value <= count; value++ {
			inputs <- value
		}
		close(inputs)
	}()

	for value := range inputs {
		outputs = append(outputs, value*value)
	}

	total := 0
	for _, value := range outputs {
		total += value
	}

	fmt.Println("count=", count)
	fmt.Println("outputs=", outputs)
	fmt.Println("total=", total)
}
  1. count ← 3, inputs ← (chan int)(⟨addr A⟩), outputs ← []int{}

    5func main() {6  var count→ 3 = 3 //@count=2, 47  inputs→ (chan int)(⟨addr A⟩) := make(chan int)8  outputs→ []int{} := []int{}910  go func() {11    for value := 1; value <= count; value++ {12      inputs <- value13    }14    close(inputs)15  }()
  2. for value := 1; value <= count; value++

    pass 1 of 3
    10go func() {11  for value1 := 1; value <= count3; value++ {12    inputs(chan int)(⟨addr A⟩) <- value113  }
    All 3 passes — pass 1 is the card above
    passvalue
    11
    22
    33
  3. outputs ← []int{1}

    pass 1 of 3
    17for value1 := range inputs(chan int)(⟨addr A⟩) {18  outputs→ []int{1} = append(outputs, value1*value)19}
    All 3 passes — pass 1 is the card above
    passvalueoutputs
    11[]int{} []int{1}
    22[]int{1} []int{1, 4}
    33[]int{1, 4} []int{1, 4, 9}
  4. close(inputs)

    13  }14  close(inputs(chan int)(⟨addr A⟩))15}()
  5. total ← 0

    21total→ 0 := 022for _, value := range outputs {
  6. total ← 1

    pass 1 of 3
    21total := 022for _, value1 := range outputs[]int{1, 4, 9} {23  total→ 1 += value124}
    All 3 passes — pass 1 is the card above
    passvaluetotal
    110 1
    241 5
    395 14
  7. fmt.Println("count=", count)

    26  fmt.Println("count=", count3)27  fmt.Println("outputs=", outputs[]int{1, 4, 9})28  fmt.Println("total=", total14)29}
    outputcount= 3
    outputs= [1 4 9]
    total= 14
  1. count ← 2, inputs ← (chan int)(⟨addr A⟩), outputs ← []int{}

    5func main() {6  var count→ 2 = 27  inputs→ (chan int)(⟨addr A⟩) := make(chan int)8  outputs→ []int{} := []int{}910  go func() {11    for value := 1; value <= count; value++ {12      inputs <- value13    }14    close(inputs)15  }()
  2. for value := 1; value <= count; value++

    pass 1 of 2
    10go func() {11  for value1 := 1; value <= count2; value++ {12    inputs(chan int)(⟨addr A⟩) <- value113  }
  3. for value := 1; value <= count; value++

    pass 2 of 2
    10go func() {11  for value2 := 1; value <= count2; value++ {12    inputs(chan int)(⟨addr A⟩) <- value213  }
  4. outputs ← []int{1}

    pass 1 of 2
    17for value1 := range inputs(chan int)(⟨addr A⟩) {18  outputs→ []int{1} = append(outputs, value1*value)19}
  5. outputs ← []int{1, 4}

    pass 2 of 2
    11  for value := 1; value <= count; value++ {12    inputs(chan int)(⟨addr A⟩) <- value213  }14  close(inputs(chan int)(⟨addr A⟩))15}()1617for value2 := range inputs(chan int)(⟨addr A⟩) {18  outputs→ []int{1, 4} = append(outputs, value2*value)19}
  6. total ← 0

    21total→ 0 := 022for _, value := range outputs {
  7. total ← 1

    pass 1 of 2
    21total := 022for _, value1 := range outputs[]int{1, 4} {23  total→ 1 += value124}
  8. total ← 5

    pass 2 of 2
    21total := 022for _, value4 := range outputs[]int{1, 4} {23  total→ 5 += value424}
  9. fmt.Println("count=", count)

    26  fmt.Println("count=", count2)27  fmt.Println("outputs=", outputs[]int{1, 4})28  fmt.Println("total=", total5)29}
    outputcount= 2
    outputs= [1 4]
    total= 5
  1. count ← 4, inputs ← (chan int)(⟨addr A⟩), outputs ← []int{}

    5func main() {6  var count→ 4 = 47  inputs→ (chan int)(⟨addr A⟩) := make(chan int)8  outputs→ []int{} := []int{}910  go func() {11    for value := 1; value <= count; value++ {12      inputs <- value13    }14    close(inputs)15  }()
  2. for value := 1; value <= count; value++

    pass 1 of 4
    10go func() {11  for value1 := 1; value <= count4; value++ {12    inputs(chan int)(⟨addr A⟩) <- value113  }
    All 4 passes — pass 1 is the card above
    passvalue
    11
    22
    33
    44
  3. outputs ← []int{1}

    pass 1 of 4
    17for value1 := range inputs(chan int)(⟨addr A⟩) {18  outputs→ []int{1} = append(outputs, value1*value)19}
    All 4 passes — pass 1 is the card above
    passvalueoutputs
    11[]int{} []int{1}
    22[]int{1} []int{1, 4}
    33[]int{1, 4} []int{1, 4, 9}
    44[]int{1, 4, 9} []int{1, 4, 9, 16}
  4. total ← 0

    21total→ 0 := 022for _, value := range outputs {
  5. total ← 1

    pass 1 of 4
    21total := 022for _, value1 := range outputs[]int{1, 4, 9, 16} {23  total→ 1 += value124}
    All 4 passes — pass 1 is the card above
    passvaluetotal
    110 1
    241 5
    395 14
    41614 30
  6. fmt.Println("count=", count)

    26  fmt.Println("count=", count4)27  fmt.Println("outputs=", outputs[]int{1, 4, 9, 16})28  fmt.Println("total=", total30)29}
    outputcount= 4
    outputs= [1 4 9 16]
    total= 30