go语言学习笔记—进阶—并发编程:为函数创建goroutine(代码片段)

Locutus Locutus     2023-01-19     761

关键词:

使用go关键字为一个函数创建一个goroutine。函数与goroutine是一对多的关系,即可以为一个函数创建多个goroutine,一个goroutine必定只对应一个函数。

为普通函数创建goroutine

  • 格式

为一个go函数创建goroutine,写法如下:

go 函数名( 参数列表 ) 

其中,函数名是要调用创建goroutine的funcName;参数列表是函数入参。使用go关键字创建goroutine时,函数的返回值会被忽略。

注:如果想要在goroutine中返回数据,我们需要使用通道channel,把数据从goroutine中作为返回值传出。

  • 例子

命令行不断输出tick n,同时可以接收用户输入,两个操作同时进行。

package main

import (
	"fmt"
	"time"
)

func running() 
	var times int
	for                          // 构建一个无限循环
		times++
		fmt.Println("tick", times) // 输出times变量的值

		time.Sleep(time.Second)    // time.Sleep延时1秒,之后继续循环
	


func main() 
	go running()                 // 使running()函数和main()函数并发执行

	var input string
	fmt.Scanln(&input)          // 接收用户输入,直到按回车键把命令行输入内容写入input变量
	fmt.Println(input)          // 输出input内容


/*
在go语言中,runtime运行时会默认为main()函数创建一个goroutine。

在本例中,main()函数的goroutine创建运行后,执行到go running()时,go调度系统又为running()函数
函数创建了一个goroutine,running()函数在自己的goroutine中运行。

此时通过go语言的调度机制,程序有两个goroutine同时运行。
*/



为匿名函数创建goroutine

  • 格式

使用匿名函数或闭包创建goroutine时,需要定义函数、参数列表、函数列表、入参列表。

go func(参数列表) 
    函数体
(入参列表)
  • 例子

在main()函数中创建一个匿名函数,并为匿名函数启动goroutine。

package main

import (
    "fmt"
    "time"
)


func main() 
    go func()                         // 使running()函数和main()函数并发执行
        var times int
    
        for                           // 构建一个无限循环
            times++ 
            fmt.Println("tick", times) // 输出times变量的值

            time.Sleep(time.Second)    // time.Sleep延时1秒,之后继续循环
        
    ()

    var input string
    fmt.Scanln(&input)          // 接收用户输入,直到按回车键把命令行输入内容写入input变量
    fmt.Println(input)          // 输出input内容

所有goroutine都会在main()结束时,一同结束。goroutine类似于线程,但从调度性能上没有线程细致。细致程度取决于goroutine调度器的实现和运行环境。终止goroutine的最好方法是自然返回goroutine对应的函数。虽然可以用 golang.org/x/net/context 包进行goroutine生命周期控制,但此法处于内测阶段。现在还没有办法获取goroutine的ID。

go语言学习笔记—进阶—并发编程:通道(channel)——使用channel收发数据(代码片段)

创建channel之后,我们可以使用channel进行数据收发操作。使用channel发送(填充)数据使用特殊的操作符<-,把数据通过channel发送。格式通道变量<-值通道变量是上文通过make创建的通道实例;值可以是变量... 查看详情

go语言学习笔记—进阶—并发编程:调整并发的运行性能(gomaxprocs)(代码片段)

go语言的运行时(runtime)实现了一个小型任务调度器,它类似于操作系统的线程调度,可以高效地把CPU资源分配给每一个任务。通过runtime.GOMAXPROCS()函数,可以指定线程池中线程与CPU核心数量的对应关系,如下:... 查看详情

go语言学习笔记—进阶—并发编程:通道(channel)——在多个goroutine之间通信的管道(代码片段)

单纯地并发执行函数是无意义的,函数之间需要交换数据才能体现并发执行的意义。虽然可以使用“共享内存”的方式交换数据,但共享内存在不同goroutine间易发生竞态问题。为了保证数据交换的正确性,必须使用互... 查看详情

go语言学习笔记—进阶—并发编程:go语言的协程goroutine,与普通程序的协程coroutine

拿Python程序的coroutine与Go程序的goroutine做比较,两者都可以把函数或语句运行在独立的环境,但还是有不同点:goroutine可能并行执行,但coroutine始终顺序执行狭义地说,goroutine可能发生在多线程环境下。goroutine... 查看详情

go语言学习笔记—进阶—并发编程:通道(channel)——各种各样的通道(代码片段)

单向通道在声明通道时,我们可以设置只发送或只接收。这种被约束操作方向的通道称为单向通道。声明单向通道只发送:chan<-,只接收:<-chanvar通道实例chan<-元素类型//只发送数据var通道实例<-chan元素... 查看详情

go语言学习笔记—进阶—并发编程:同步sync,竞态检测——检测代码在并发环境下出现的问题(代码片段)

使用channel在多个goroutine之间交换数据,只是数据同步方法的一种。通道内部的实现依然使用各种锁。优雅代码的代行是性能。在某些轻量级场合,原子访问(atomic包)、互斥锁(sysnc.Mutex)以及等待组࿰... 查看详情

go语言学习笔记—进阶—并发编程(11):同步sync,等待组(sync.waitgroup)——保证在并发环境中完成指定数量的任务(代码片段)

除了使用通道channel和互斥锁sync.Mutex进行两个并发程序间的同步,我们还可以使用等待组(sync.WaitGroup)进行多个任务之间的同步。方法名功能(wg*WaitGroup)Add(deltaint)等待组的计数器+1(wg*WaitGroup)Done()等待组的计数器-1(... 查看详情

2.1go微服务实战(go语言进阶)---并发编程进阶

第8章 并发编程进阶8.1 竞态与并发模式 8.1.1 数据竞态 8.1.2 并发原理8.2 sync包 8.2.1 sync.Mutex互斥锁 8.2.2 sync.RWMutex多读写锁 8.2.3 sync.Once 8.2.4 sync.Cond 8.2.5 sync.Pool 8.2.6 sync.Map8.3 context包 8.3.1 应用场景 8.3.2 定义 8.3.3... 查看详情

go语言学习笔记—进阶—并发编程(10):读写互斥锁(sync.rwmutex)——在读比写多的环境下,比互斥锁更高效(代码片段)

在读多写少的场景中,可以优先使用读写互斥锁,sync包中的RWMutex提供了读写互斥锁的封装。var(countint//某个逻辑中使用的变量,如包级别变量、结构体成员字段变量countGuardsync.RWMutex//变量名+Guard,以表示这个... 查看详情

go语言学习笔记—进阶—并发编程:互斥锁(sync.mutex)——保证同时只有一个goroutine可以访问共享资源(代码片段)

互斥锁(英语:Mutualexclusion,缩写Mutex)是一种在多线程编程中,防止两条线程同时对同一共享资源(比如全局变量)进行读写的机制。互斥锁通过把代码切片成一个个的临界区域(criticalsection࿰... 查看详情

对于go语言的进阶与依赖管理|青训营笔记(代码片段)

一.Go语言进阶与依赖管理1.1并发和并行Go可以充分发挥多核优势,高效运行。多线程程序在单核心的cpu上运行,称为并发;多线程程序在多核心的cpu上运行,称为并行。并发与并行并不相同,并发主要由切换时间片来实现“同时... 查看详情

go笔记(十五):并发编程(代码片段)

一、协程的创建  Go语言支持并发,只需要通过go关键字来开启goroutine(协程)即可。  goroutine(协程)是轻量级线程,goroutine(协程)的调度是由Golang运行时进行管理的。goroutine语法格式(创建协程):go函数名(参数列表)示例代码如... 查看详情

vue学习笔记进阶篇——render函数

本文为转载,原文:Vue学习笔记进阶篇——Render函数基础Vue推荐在绝大多数情况下使用template来创建你的HTML。然而在一些场景中,你真的需要JavaScript的完全编程的能力,这就是 render函数,它比template更接近编译器。<h1>&l... 查看详情

javascript进阶笔记

js是一门函数式语言,因为js的强大威力依赖于是否将其作为函数式语言进行使用。在js中,我们通常要大量使用函数式编程风格。函数式编程专注于:少而精、通常无副作用、将函数作为程序代码的基础构件块。在函数式编程中... 查看详情

go语言并发编程

通道(channel)单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。虽然可以使用共享内存进行数据交换,但是共享内存在不同的goroutine中容易发生竞态问题。为了保证数据交换的正... 查看详情

使用go语言实现高效的并发编程(代码片段)

文章目录概述举个例子使用并发编程来实现简单的任务处理使用同步锁来避免竞态条件使用信道来协调多个goroutine之间交互总结概述Go语言支持并发编程。你可以通过创建多个并发单元(称为goroutines)来实现多线程编程... 查看详情

使用go语言实现高效的并发编程(代码片段)

文章目录概述举个例子使用并发编程来实现简单的任务处理使用同步锁来避免竞态条件使用信道来协调多个goroutine之间交互总结概述Go语言支持并发编程。你可以通过创建多个并发单元(称为goroutines)来实现多线程编程... 查看详情

go基础编程day-1

Go语言的特性开启了学习新的语言路程,记录每天学习的笔记,与大家一起分享。  ①、自动垃圾回收  ②、更丰富的内置类型  ③、函数多返回值  ④、错误处理  ⑤、匿名函数和闭包  ⑥、类型和接口  ⑦、... 查看详情