这个管道模式的示例是Golang实现的吗?

这个管道模式的示例是Golang实现的吗?

package main

import (
	"fmt"
	"time"

	"github.com/fatih/color"
)

func double(input chan int) chan int {
	resultChan := make(chan int)
	go func() {
		defer close(resultChan)
		for {
			select {
			case i, ok := <-input:
				if ok == false {
					color.Cyan("done its closed returing")
					return
				}
				resultChan <- i + i
			}
		}
	}()
	return resultChan
}

func square(input chan int) chan int {
	resultChan := make(chan int)
	go func() {
		defer close(resultChan)
		for x := range input {
			resultChan <- x * x
		}
	}()
	return resultChan
}

func prefix(input chan int) chan string {
	resultChan := make(chan string)
	go func() {
		defer close(resultChan)
		for x := range input {
			resultChan <- fmt.Sprintf("##### %d", x)
		}
	}()
	return resultChan
}

func print_me(input chan string) {
	go func() {
		for {
			select {
			case x, ok := <-input:
				if ok == false {
					return
				}
				fmt.Println(x)
			}
		}
	}()
}

func main() {
	inputChan := make(chan int)

	d := double(inputChan)
	s := square(d)
	p := prefix(s)
	print_me(p)

	for x := 0; x < 10; x++ {
		inputChan <- x
		time.Sleep(500 * time.Millisecond)
	}

	close(inputChan)

}

更多关于这个管道模式的示例是Golang实现的吗?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

vizvasrj:

你好 @vizvasrj

是的,这是一个很好的管道(pipeline)示例。让我们来看看这个管道: 第一阶段,在 main() 函数中,你将数据(数字)送入一个名为 inputChan 的通道。 第二阶段是 double 方法。 第三阶段是 square。 第四阶段是 prefix。 第五阶段是 print_me

请记住,虽然这是一个管道模式的基础示例,但在各个阶段中你可以做更复杂的事情。你可以看看这里,了解针对管道可能遇到的各种问题的6个巧妙解决方案:Go Concurrency Patterns: Pipelines and cancellation - The Go Programming Language

更多关于这个管道模式的示例是Golang实现的吗?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,这个管道模式示例是用Go语言实现的。这是一个典型的生产者-消费者管道模式,展示了Go的并发特性。

示例中的管道由四个阶段组成:

  1. double - 将输入值翻倍
  2. square - 计算平方值
  3. prefix - 添加前缀字符串
  4. print_me - 打印结果

每个阶段都通过goroutine和channel进行通信:

// 管道连接方式
d := double(inputChan)    // 第一阶段:翻倍
s := square(d)           // 第二阶段:平方
p := prefix(s)           // 第三阶段:添加前缀
print_me(p)              // 第四阶段:打印

需要注意的一个问题是print_me函数中的goroutine可能会阻塞主goroutine的退出。建议使用sync.WaitGroup来确保所有goroutine完成:

func print_me(input chan string, wg *sync.WaitGroup) {
    wg.Add(1)
    go func() {
        defer wg.Done()
        for x := range input {
            fmt.Println(x)
        }
    }()
}

func main() {
    var wg sync.WaitGroup
    inputChan := make(chan int)

    d := double(inputChan)
    s := square(d)
    p := prefix(s)
    print_me(p, &wg)

    for x := 0; x < 10; x++ {
        inputChan <- x
        time.Sleep(500 * time.Millisecond)
    }

    close(inputChan)
    wg.Wait() // 等待所有goroutine完成
}

这个示例展示了Go语言通过channel和goroutine实现管道模式的简洁性和高效性。

回到顶部