条件化的Go协程/通道

huangapple go评论85阅读模式
英文:

Conditional Go Routine/Channel

问题

我想将统计程序设为有条件运行,只在某些情况下运行,否则会浪费一半的时间。目前,我有一个goroutine作为生产者,通过缓冲通道向两个消费者goroutine提供数据。有没有办法使统计程序有条件运行,或者有没有更好的模式可以遵循?非常感谢您提前的任何帮助!

func main() {
    options()
    go produce(readCSV(loc))
    go process()
    go statistics() // 仅在标志位为真时运行
    <-done
}

func produce(entries [][]string) {
    regex, err := regexp.Compile(reg)
    if err != nil {
        log.Error(reg + ", 不是一个有效的正则表达式")
    } else {
        for _, each := range entries {
            if regex.MatchString(each[col]) {
                matches <- each
                stats <- each // 仅在标志位为真时运行
            }
        }
    }
    done <- true
}

func process() {
    for {
        match := <-matches
        if len(match) != 0 {
            // 处理
        }
    }
}

func statistics() {
    for {
        stat := <-stats
        if len(stat) != 0 {
            // 统计
        }
    }
}
英文:

I would like to make the statistics routine conditional so that it only runs on certain cases otherwise it will waste cycles half the time. Right now I have one go routine act as a producer to feed the two consumer routines via buffered channels. Is there a way I can make it so the statistics routine is conditional or is there a better pattern I should follow? Thanks in advance for any and all help!

func main() {
	options()
	go produce(readCSV(loc))
	go process()
	go statistics() // only on flag
	&lt;-done
}

func produce(entries [][]string) {
	regex, err := regexp.Compile(reg)
	if err != nil {
		log.Error(reg + &quot;, is not a valid regular expression&quot;)
	} else {
		for _, each := range entries {
			if regex.MatchString(each[col]) {
				matches &lt;- each
				stats &lt;- each // only on flag
			}
		}
	}
	done &lt;- true
}

func process() {
	for {
		match := &lt;-matches
		if len(match) != 0 {
			// PROCESS
		}
	}
}

func statistics() {
	for {
		stat := &lt;-stats
		if len(stat) != 0 {
			// STATISTICS
		}
	}
}

答案1

得分: 1

这个条件语句没有问题:

var stats chan []string  // 不要初始化 stats.

func main() {
    options()
    go produce(readCSV(loc))
    go process()
    if flag {
        stats = make(chan []string, 1024)
        go statistics() // 只在 flag 为真时执行
    }
    <-done
}

func produce(entries [][]string) {
    regex, err := regexp.Compile(reg)
    if err != nil {
        log.Error(reg + " 不是一个有效的正则表达式")
    } else {
        for _, each := range entries {
            if regex.MatchString(each[col]) {
                matches <- each
                if stats != nil {
                    stats <- each // 只在 flag 为真时执行
                }
            }
        }
    }
    close(done)
}

func process() {
    for {
        select {
        case match := <-matches:
            if len(match) != 0 {
              // 处理
            }
        case <-done:
            return
        }
    }
}

func statistics() {
    for {
        select {
        case stat := <-stats:
            if len(stat) != 0 {
                // 统计
            }
        case <-done:
            return
        }
    }
}
英文:

There is nothing wrong with making this conditional:

var stats chan []string  // Don&#39;t initialize stats.

func main() {
    options()
    go produce(readCSV(loc))
    go process()
    if flag {
        stats = make(chan []string, 1024)
        go statistics() // only on flag
    }
    &lt;-done
}

func produce(entries [][]string) {
    regex, err := regexp.Compile(reg)
    if err != nil {
        log.Error(reg + &quot;, is not a valid regular expression&quot;)
    } else {
        for _, each := range entries {
            if regex.MatchString(each[col]) {
                matches &lt;- each
                if stats != nil {
                    stats &lt;- each // only on flag
                }
            }
        }
    }
    close(done)
}

func process() {
    for {
        select {
        case match := &lt;-matches:
            if len(match) != 0 {
              // PROCESS
            }
        case &lt;-done:
            return
        }
    }
}

func statistics() {
    for {
        select {
        case stat := &lt;-stats:
            if len(stat) != 0 {
                // STATISTICS
            }
        case &lt;-done:
            return
        }
    }
}

答案2

得分: 0

也许你正在寻找flag包。

import "flag"

var withStats = flag.Boolean("s", false, "进行统计")

func main() {
    flag.Parse()
    ...
    if *withStats == true {
        t := statType
        size := 100
        stats := make(chan, t, size)
        go statistics() // 仅在标志上
    }
    ...
}
英文:

Perhaps you're looking for the flag package.

import &quot;flag&quot;

var withStats = flag.Boolean(&quot;s&quot;, false, &quot;Do statistics&quot;)

func main() {
	flag.Parse()
	...
	if *withStats == true {
        t := statType
        size := 100
        stats := make(chan, t, size)
		go statistics() // only on flag
	}
    ...
}

答案3

得分: 0

如果你在代码中从多个地方更新统计数据,你可能想要添加一些辅助方法。类似这样:

type stats struct {
    ch chan []string
}

func (s *stats) update(a []string) {
    if s != nil {
        s.ch <- a
    }
}

func (s *stats) start() {
    if s != nil {
        s.ch = make(chan []string)
        go statistics()
    }
}

var s *stats
if enabled {
    s = new(stats)
}
s.start()

// 代码的其他部分
s.update(each)

希望这能帮到你!

英文:

If you update statistics from many places in your code you might want to add some helper methods. Something like:

type stats struct {
    ch chan []string
}

func (s *stats) update(a []string) {
	if s != nil {
		s.ch &lt;- a
	}
}

func (s *stats) start() {
	if s != nil {
		s.ch = make(chan []string)
		go statistics()
	}
}

var s *stats
if enabled {
    s = new(stats)
}
s.start()

// later in the code
s.update(each)

huangapple
  • 本文由 发表于 2015年7月8日 11:03:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/31282829.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定