go协程

 channel

无缓冲channel 

func main() {
	ch := make(chan int) //无缓冲的channel
	go func () {
		time.Sleep(time.Second)
		fmt.Println("finish?")
		<-ch    //阻塞,直到channel有值
	}()
	ch <- 1    //阻塞,直到channel内值传出
	fmt.Println("yes")
}
// 输出结果:
// finish?
// yes

 带缓冲channel

func mirroredQuery() string {
    responses := make(chan string, 3)  //可通过cap()得到容量,此时是3;len()得到有效元素的个数,此时是0
    go func() { responses <- request("asia.gopl.io") }()
    go func() { responses <- request("europe.gopl.io") }()
    go func() { responses <- request("americas.gopl.io") }()
    return <-responses // 返回最先得到的response,后面不使用该channel时,会自动垃圾回收
}  //如果这里使用的是无缓冲channel,其中两个协程会一直阻塞在那里,不会进行垃圾回收

func request(hostname string) (response string) { /* ... */ }

 channel的close()

func main() {
	naturals := make(chan int)
	squares := make(chan int)

	go func() {
		for x := 0; x < 100; x++ {
			naturals <- x
		}
		close(naturals)
	}()

	go func() {
		for x := range naturals {  //当channel被关闭并且没有值可接收时跳出循环
			squares <- x * x
		}
		close(squares)
	}()

	for x := range squares {
		fmt.Println(x)
	}
        m,ok := <-squares  //当channel被关闭后,再传入值会发起panic,而且传出操作不再阻塞
	fmt.Println(m,ok)  //打印结果:0 false。第二个返回值,ture表示成功从channels接收到值,false表示channels已经被关闭并且里面没有值可接收
}
//不管一个channel是否被关闭,当它没有被引用时将会被Go语言的垃圾自动回收器回收。

单方向channel 

func counter(out chan<- int) {
    for x := 0; x < 100; x++ {
        out <- x
    }
    close(out)  //可以关闭chan<-类型,关闭<-chan类型会报错
}

func squarer(out chan<- int, in <-chan int) {
    for v := range in {
        out <- v * v
    }
    close(out)
}

func printer(in <-chan int) {
    for v := range in {
        fmt.Println(v)
    }
}

func main() {
    naturals := make(chan int) 
    squares := make(chan int)
    go counter(naturals)  //传入双向chan,可自动转换为单向chan。但不可反过来
    go squarer(squares, naturals)
    printer(squares)
}

select

select {  //选择一个优先完成通讯的分支执行,如果没有default分支,会阻塞直到其中一个有通讯产生;如果有多个分支都满足,随机选择一个执行
case <-chan1:
    //...
case <-chan2:
    //...
case <-chan3:
    //...
default:
    //...
}

 

sync

func main(){
	var l sync.Mutex
	var w sync.WaitGroup
	var counter int
	w.Add(5000)    //或者在每个go协程之前w.Add(1)
	for i := 0; i < 5000; i++{
                //w.Add(1)
		go func(){
			l.Lock()  //加锁保护共享变量,必须在本协程内解锁,其他协程才能操作该变量
			counter ++
			l.Unlock()
			w.Done()
		}()
	}
	w.Wait()  //阻塞,直到执行了5000次w.Done()
	fmt.Println(counter)
}

//输出结果:5000

//当获得锁的大部分goroutine都是读操作,可以使用sync.RWMutex及其方法Rlock()、RUnlock(),其允许多个只读操作并行执行,但写操作会完全互斥。这种锁叫作“多读单写”锁(multiple readers, single writer lock)

//sync.Once,其内部包含一个mux和bool,第一次调用Do时,执行传入的函数并将bool置位true,此后再调用Do时发现bool为true就不再执行传入的函数
//往往用在需要一次性的初始化时
var once sync.Once
for i := 0; i < 1000; i++{
	go func (){
		once.Do(init)
		do something...
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值