package main import ( "fmt" "runtime" ) func main() { //goroutine 其实就是线程,但它比线程小,执行goroutine时只需较少的栈内存(4~5KB) //c#中新建一个thread要分配1M的内存栈。所以,goroutine可以同时运行比较多的并发任务 //goroutine也正是因为这个原因比thread更易用、更高效、更轻便 //goroutine 通过关键字go实现,go funcName(参数) //示例 //go sayHello("anther--Hello") //sayHello("main--World") //channels,channel类型,可以接收和发送数据 //必须使用make来创建channel并指定要发送到channel的值的类型 //ci := make(chan int) //可以发送int到ci这个channel(从这个channel取出的也是int类型) //cs := make(chan string) //可以发送string到string这个channel(从这个channel取出的也是string类型) //cf := make(chan interface{}) //可以发送interface{}到cf这个channel(从这个channel取出的也是interface{}类型) //ch <- v //将v发送到channel ch //v := <-ch //从channel中取值并赋值给v //示例 /* arr := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(arr[:len(arr)/2], c) go sum(arr[len(arr)/2:], c) x, y := <-c, <-c fmt.Println(x, y, x+y) */ //Buffered Channels //下面这个channel只有存4个int类型的数据,写入前4个时,不会阻塞 , //当写入第5个时,需要从chanel中读出1个,空出空间才能继续写入 //ch := make(chan int, 4) //range、close 遍历和读取channel //for i := range c能够不断的读取channel里面的数据,直到该channel被显式的关闭 //应该在生产者的地方关闭channel,而不是消费的地方去关闭它,这样容易引起panic //消费方可以通过语法v, ok := <-ch测试channel是否被关闭。 //如果ok返回false,那么说明channel已经没有任何数据并且已经被关闭。 /* ch := make(chan int, 10) go fibonacci(cap(ch), ch) for value := range ch { fmt.Printf("%d\t", value) } */ //select 类似于switch,选择一个符合条件的channel执行 //select 也有一个default:它是当channel阻塞(即没有空间)时执行 c := make(chan int) quit := make(chan int) go func() { for i := 0; i < 10; i++ { fmt.Println(<-c) } quit <- 0 }() fibonacciSelect(c, quit) //runtime中的goroutine函数 //退出当前执行的goroutine,但是defer函数还会继续调用 Goexit() //sleep让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。 Gosched() //返回 CPU 核数量 NumCPU() //返回正在执⾏行和排队的任务总数 NumGoroutine() //用来设置可以运行的CPU核数 GOMAXPROCS() } func sayHello(str string) { for i := 0; i < 5; i++ { //相当于c#中的sleep() runtime.Gosched() fmt.Println(str) } } func sum(a []int, c chan int) { sum := 0 for _, value := range a { sum += value } c <- sum } func fibonacci(n int, c chan int) { x, y := 1, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func fibonacciSelect(c, quit chan int) { x, y := 1, 1 for { select { case c <- x: x, y = y, x+y case <-quit: fmt.Println("quit") return //default: // 当c阻塞的时候执行这里 } } }