golang中几种对goroutine的控制方法

我们先看一段代码

func listen() {
	ticker := time.NewTicker(time.Second)
	for {
		select {
		case <-ticker.C:
			fmt.Println(time.Now())
		}
	}
}
func main() {
	go listen()
	time.Sleep(time.Second * 5)
	fmt.Println("main exit")
}

非常简单的一个goroutine用法,想必每个gopher都看过的。

不过在实际生产中,我们几乎看不到这种用法的的身影,原因很简单,我们无法实现对goroutine的控制,而一般业务中我们需要根据不同情况对goroutine进行各种操作。

要实现对goroutine的控制,一般有以下两种。

一、手动发送goroutine控制信号

这里我们发送一个退出goroutine的信号。

// listen 利用只读chan控制goroutine的退出
func listen(ch <-chan bool) {
	ticker := time.NewTicker(time.Second)
	for {
		select {
		case <-ticker.C:
			fmt.Println(time.Now())
		case <-ch:
			fmt.Println("goroutine exit")
			return
		}
	}
}

func main() {
	// 声明一个控制goroutine退出的chan
	ch := make(chan bool, 1)
	go listen(ch)

	// 只写chan
	func(ch chan<- bool) {
		time.Sleep(time.Second * 3)
		fmt.Println("发送退出chan信号")
		ch <- true
		close(ch)
	}(ch)

	time.Sleep(time.Second * 5)
	fmt.Println("main exit")
}

我们在main函数里发送一个控制goroutine的退出信息,在goroutine里我们会select这个通道,如果收到此信息,则直接退出goroutine。这里我们使用到了单向chan。

Continue reading

Golang遍历切片删除元素引起恐慌问题

删除一个切片的一些元素,https://github.com/golang/go/wiki/SliceTricks告知切片操作:Golang遍历切片恐慌时删除元素

a = append(a[:i], a[i+1:]...)

然后我下面的编码:

package main 

import (
    "fmt" 
) 

func main() { 
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 
    for i, value := range slice { 
     if value%3 == 0 { // remove 3, 6, 9 
      slice = append(slice[:i], slice[i+1:]...) 
     } 
    } 
    fmt.Printf("%vn", slice) 
} 

go run hello.go,它恐慌:

panic: runtime error: slice bounds out of range 

goroutine 1 [running]: 
panic(0x4ef680, 0xc082002040) 
    D:/Go/src/runtime/panic.go:464 +0x3f4 
main.main() 
    E:/Code/go/test/slice.go:11 +0x395 
exit status 2 

我该如何更改此代码才能正确使用?

想到的有几下几种方法

1、使用goto和标签

func main() { 
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} 
Label: 
    for i, n := range slice { 
     if n%3 == 0 { 
      slice = append(slice[:i], slice[i+1:]...) 
      goto Label 
     } 
    } 
    fmt.Printf("%vn", slice) 
} 

它的工作原理很简单,就是不停的迭代,每次删除一个元素后,都需要从切片的开头重新迭代,太过于效率低下了,特别是当一个切片很大的情况下。

Continue reading