首页 > 其他分享 >golang基础--Goroutine与Channel

golang基础--Goroutine与Channel

时间:2023-05-06 18:33:36浏览次数:27  
标签:Goroutine -- goroutine chan golang int channel main Channel

什么是goroutine?

  goroutine是go特有的并发体,是一种轻量级的线程,由go关键字启动。goroutine是Go语言提供的一种用户态线程,有时我们也称之为 协程。所谓的协程,某种程度上也可以叫做轻量线程,它不由os,而由应用程序创建和管理,因此使用 开销较低(一般为4K)。我们可以创建很多的goroutine,并且它们跑在同一个内核线程之上的时 候,就需要一个调度器来维护这些goroutine,确保所有的goroutine都使用cpu,并且是尽可能公平的使用cpu资源。

什么是Channel?

  Channel是goroutine之间互相通信的通道,goroutine可以通过它来发送消息和接收消息。

  通常,通过make来初始化一个channel

  channel_test1 := make(chan int)

  当通道变量创建好后,即可以使用该变量进行数据的发送,接收和关闭。数据的发送和接收均适用“<-”符号,关闭则使用close函数。

  注意:一但通道关闭,就无法通过这个通道发送数据了,但不会影响数据的接收,直到通道中的数据队列为空。此时,若尝试再次获取数据,将返回对应类型的默认值。另外,close函数无法关闭一个已经关闭的channel。

无缓冲的channel

  无缓冲channel只有在等待接收数据的时候,才能成功发送数据。

  示例代码:

package main

import (
    "fmt"
    "reflect"
    "time"
)

func IntChanRecvListener(intChan chan int) {
    intValue := <-intChan
    fmt.Println(intValue, reflect.TypeOf(intValue))
}

func main() {
    var intChan = make(chan int)
    fmt.Println(intChan, reflect.TypeOf(intChan))
    go IntChanRecvListener(intChan)
    intChan <- 100
    close(intChan)
    time.Sleep(time.Second)
}

 

   无缓冲的channel要求数据的发送和接收必须成对出现,必须先有数据的接收者,且数据的发送和接收必须同步。

 

带缓冲的Channel

  再使用make穿件channel变量时,可以通过定义缓冲区大小来构建带缓冲的channel。带缓冲的channel不要求必须有数据的接收者才能成功发送数据。使用内置函数len获取channel中元素的数量,cap获取channel缓冲区的大小。

  示例代码:

package main

import (
    "fmt"
    "time"
)

func IntChanRecListener(intChan chan int) {
    intValue := <-intChan
    //fmt.Println(intValue, reflect.TypeOf(intValue))
    fmt.Println("成功接收第第1个value,通道元素个数,当前缓冲区大小:", intValue, len(intChan), cap(intChan))
    intValue = <-intChan
    //fmt.Println(intValue, reflect.TypeOf(intValue))
    fmt.Println("成功接收第第2个value,通道元素个数,当前缓冲区大小:", intValue, len(intChan), cap(intChan))
}

func main() {
    var intChan2 = make(chan int, 2)
    intChan2 <- 100
    fmt.Println(len(intChan2), cap(intChan2))
    intChan2 <- 200
    fmt.Println(len(intChan2), cap(intChan2))
    go IntChanRecListener(intChan2)
    time.Sleep(time.Second * 2)
    close(intChan2)

}

 判断Channel是否关闭

  再使用channel读取数据时,可以获得两个返回值:一个是获取的值,一个是布尔值,当channel关闭后,为false,否则为true

   示例代码:

package main

import "fmt"

//判断channel是否关闭

func main() {
    initchan := make(chan int, 10)
    initchan <- 1
    initchan <- 2
    initchan <- 3
    close(initchan)
    for {
        initvalue, isOpen := <-initchan
        if !isOpen {
            fmt.Println("channel 已经关闭")
            break
        }
        fmt.Println(initvalue)
    }

}

 Select结构

  select结构类似switch--case结构,也由若干个分支及一个默认分枝构成,每个case分支对应一条channel的数据收发操作。select结构会同时监听一个或多个channel,简化处理多个channel的流程。

  示例代码:

package main

//select 的用法:select结构会同时监听一个或多个通道,简化处理多个通道的流程。
import (
    "fmt"
    "time"
)

func sendFunc1(chan1 chan int) {
    for i := 0; i < 5; i++ {
        chan1 <- i
        time.Sleep(1 * time.Second)
    }
}
func sendFunc2(chan2 chan int) {
    for i := 10; i >= 5; i-- {
        chan2 <- i
        time.Sleep(1 * time.Second)
    }
}
func recvFunc(chan1 chan int, chan2 chan int) {
    for {
        select {
        case intvalue1 := <-chan1:
            fmt.Println("接收到chan1通道的值:", intvalue1)
        case intvalue2 := <-chan2:
            fmt.Println("接收到chan2通道的值:", intvalue2)

        }
    }
}

func main() {
    chan1 := make(chan int, 5)
    chan2 := make(chan int, 5)
    go recvFunc(chan1, chan2)
    go sendFunc1(chan1)
    go sendFunc2(chan2)
    time.Sleep(time.Second * 5)
    fmt.Println("main程序结束")
}

 

 

标签:Goroutine,--,goroutine,chan,golang,int,channel,main,Channel
From: https://www.cnblogs.com/99kol/p/17378237.html

相关文章

  • python 制作奥运五环 (turtle模块)
     importturtle#第一个圈turtle.width(10)#画笔宽度10turtle.color("black")#画笔的颜色turtle.circle(50)#半径50的圆#第二个圈turtle.penup()#抬笔turtle.goto(110,0)#去到坐标(110,0)turtle.pendown()#放笔turtle.width(10)turt......
  • 【Spring Boot】实战Spring Boot(二)——Hello World 小试牛刀
    一、前言      在上一篇博客,小编向大家介绍了SpringBoot是什么,在上面时候使用。但是空洞的理论的开始总会有一个helloworld的小程序开始,在这篇博客中,小编就向大家介绍一下使用SpringBoot完成一个Helloworld程序。二、环境准备一款不错的IDE:Eclipse、IdeaIntellij(力荐)m......
  • 【问题排查篇】一次业务问题对 ES 的 cardinality 原理探究
    作者:京东科技王长春业务问题小编工作中负责业务的一个服务端系统,使用了Elasticsearch服务做数据存储,业务运营人员反馈,用户在使用该产品时发现,用户后台统计的订单笔数和导出的订单笔数不一致!交易订单笔数不对,出现差错订单了?这一听极为震撼!出现这样的问题,在金融科技公司里面是......
  • 【MySql】Sql优化(三)——性能优化
    一、前言      当数据库数据达到一定数量的时候,结合数据库连接池Druid的可视化监控界面,对系统中运行的sql语句进行检测,对使用频繁、执行时间长的sql语句进行优化。二、优化方案原则[原则一:选择需要优化的SQL]1,选择需要优化的SQL:不是所有的SQL都需要优化,在优化的过程中,首......
  • 怎么准备Java面试(一):全局把控
    一、前言最近小编换工作,也要开始准备一下面试。小编作为一个Java开发,也是从初级——>中级——>高级——>资深。一步一步走过来的,基本面试过程中,内容是大致是一样的。下面我将从这几个分支中来依次铺展开:二、聊一聊面试大部分公司会有:一面基础面试or算法;二面项目组长深入面试......
  • spring和hibernate配置文件整合
    为了操作方便,我们经常在spring整合hibernate的WEB项目中省去了用hibernate.cfg.xml的麻烦,将hibernate的信息直接配置在Spring配置文件中下面的都是针对Spring整合Hibernate(注解方式的hibernate)来说的hibernate.cfg.xml和applicationContext.xml原始配置......
  • 使用Python扩展PAM(part 1)
    0、使用Python扩展PAM实现一些额外的功能,比如ssh、vpn等二次验证。1、准备工具实现这个功能需要用到pam_python pam-python 注意!是pam-python不是python_pamPam-python是一个开源的Python模块,用于编写自定义PAM模块。Pam-python使用Python脚本来扩展PAM功能。它使用Cython和Pyt......
  • JMS应用
    JMS应用JMS(JavaMessageService,Java消息服务)是一组Java应用程序接口(JavaAPI),它提供创建、发送、接收、读取消息的服务。由Sun公司和它的合作伙伴设计的JMSAPI定义了一组公共的应用程序接口和相应语法,使得Java程序能够和其他消息组件进行通信。JMS是......
  • Shell的参数传递
    我们可以在执行Shell脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n代表一个数字,1为执行脚本的第一个参数,2为执行脚本的第二个参数,以此类推……具体实例:以下实例我们向脚本传递三个参数,并分别输出,其中$0为执行的文件名(包含文件路径):echo"Shell传递参数实例!";echo"执行......
  • Docker备忘录
    基础知识博客园内有很多作者分享全面的Docker快速入门教程Docker与虚拟机的区别Docker架构及工作原理手把手教你安装DockerDockerfile制作自己的镜像文件Docker日常工作常用命令网络#4个模式,一般只用briagehost#直连主机IPnone#没有设置briage#虚拟网卡containe......