前面讲介绍了Go 语言的基础知识,Golang的基础语法以及Golang的主要特性Interface等。感兴趣的朋友可以先看看之前的文章。这些都是Golang的基础内容,必须熟练掌握。
接下来讲讲Golang的核心功能,也是go语言重要的特性:Go协程(Goroutine)。
Go协程(Goroutine)是与其他函数同时运行的函数。可以认为Go协程是轻量级的线程,由Go运行时来管理。不需要抢占式调度,可以有效提高线程的任务并发性,而避免多线程的缺点;
Go 协程之间通过信道(channel)进行通信,简单的说就是多个协程之间可以通过管道进行通信。这样可以防止多个协程访问共享内存时发生资源争抢的问题。
先看下面的例子:
package mainimport ( "fmt" "time")func hello() { fmt.Println("Hello world goroutine")}func main() { go hello() time.Sleep(1 * time.Second) fmt.Println("main function")}
只需要在hello() 方法前加上go关键字,就行了。是不是特别简单。
在函数调用前加上go关键字,Go运行时调用时就会在一个新的goroutine中并发执行。当被调用的函数返回时,这个goroutine也自动结束。听着感觉像C# 中的Task。
需要注意的是:如果这个函数有返回值,那么这个返回值会被丢弃。
Channel(管道) 可以被认为是协程之间通信的管道。与水流从管道的一端流向另一端一样,数据可以从信道的一端发送并在另一端接收。
1. 定义
每个channel都有一个类型。此类型是允许信道传输的数据类型。channel是类型相关的,一个channel只能传递一种类型的值,这个类型需要在声明channel时指定。
2. 声明
a. 我们需要通过内置函数 make 来创建一个信道。
下面的代码声明了一个信道:
var ch chan int
b. 与其他变量定义一样,快速声明也是定义信道的一种有效而简洁的方式:
a := make(chan int)
c. 创建一个带缓冲的channel
c := make(chan int, 1024)// 从带缓冲的channel中读数据for i:=range c { ...}
3. 发送和接收数据
通过信道发送和接收数据的语法如下:
data := <- a // 从channel a 读取数据 a <- data // 将数据写入到 channel a
箭头的指向说明了数据是发送还是接收,是不是特别简单?
下面就直接说说,Goroutine和channel 共同使用的完整例子:
package mainimport ( "fmt" "time")func Producer(queue chan<- int) { for i := 0; i < 10; i++ { queue <- i //写入 fmt.Println("create :", i) }}func Consumer(queue <-chan int) { for i := 0; i < 10; i++ { v := <-queue // 读出 fmt.Println("receive:", v) }}func main() { queue := make(chan int, 88) go Producer(queue) go Consumer(queue) time.Sleep(1 * time.Second)}
以上,就简单的介绍了Go语言中的协程(Goroutine)和信道(channel)。这两个功能特性,是go语言中重要的特性。大家可以写写其他的例子,熟悉掌握。
Golang 入门系列(四)Golang中的interface,一看就明白
Golang 入门系列(三)打好基本功: Golang 语法基础!
SpringBoot入门系列(一)如何快速创建SpringBoot项目
Nginx总结(六)nginx实现负载均衡