go并发
Goroutine 是 Go 语言支持并发的核心,在一个Go程序中同时创建成百上千个goroutine是非常普遍的,一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB。区别于操作系统线程由系统内核进行调度, goroutine 是由Go运行时(runtime)负责调度。例如Go运行时会智能地将 m个goroutine 合理地分配给n个操作系统线程,实现类似m:n的调度机制,不再需要Go开发者自行在代码层面维护一个线程池。Goroutine 是 Go 程序中最基本的并发执行单元。每一个 Go 程序都至少包含一个 goroutine——main goroutine,当 Go 程序启动时它会自动创建
func Printhello() string {
fmt.Println("hello")
return "hello"
}
func main() {
fmt.Println("主goroutine执行开始")
go Printhello()
fmt.Println("主线程执行结束")
}
信道
如果说 goroutine 是Go程序并发的执行体,channel就是它们之间的连接。channel是可以让一个 goroutine 发送特定值到另一个 goroutine 的通信机制,信道是引用类型,初始化为nil
Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型
var 信道实例 chan 信道类型
信道实例 := make(chan 信道类型)
func Printhello(c chan string) {
fmt.Println("其他goroutine执行开始")
c<-"hello"
}
func main() {
fmt.Println("主goroutine执行开始")
var a chan string=make(chan string)
go Printhello(a)
b:=<-a
fmt.Println(b)
fmt.Println("主goroutine执行结束")
}
var a chan interface{}=make(chan interface{})
func main() {
var c chan int=make(chan int)
fmt.Println("主goroutine")
go Recive(c)
c<-1
}
func Recive(c chan int){
d:=<-c
fmt.Println("信道中取值",d)
}
var a chan int= make(chan int, 3)
a<-999
a<-866
fmt.Println(<-a)
go Recive(a)
fmt.Println(len(a))
fmt.Println(cap(a))
Waitgroup
func main() {
var wg sync.WaitGroup
go task("23", &wg)
go task("王五", &wg)
go task("张三", &wg)
wg.Add(3)
wg.Wait()
fmt.Println("执行主任务结束")
}
func task(s string, wg *sync.WaitGroup) {
fmt.Println(s)
wg.Done()
}
func main() {
var wg sync.WaitGroup
for i:=0;i<5;i++{
go task1(i, &wg)
wg.Add(1)
}
wg.Wait()
fmt.Println("执行主任务结束")
func task1(s string, wg *sync.WaitGroup) {
fmt.Println(s)
wg.Done()
}
工作池
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Job struct {
Id int
RoundNum int
}
type Result struct {
Job Job
total int
}
var jobChan = make(chan Job, 10)
var resultChan = make(chan Result, 10)
func genNum(n int) {
for i:=0;i<n;i++{
randNum :=rand.Intn(999)
jobChan<-Job{Id: i,RoundNum: randNum}
}
close(jobChan)
}
func worker(wg *sync.WaitGroup) {
for job:=range jobChan{
num :=job.RoundNum
total :=0
for num!=0{
total += num % 10
num/=10
}
resultChan<-Result{Job: job,total: total}
}
wg.Done()
}
func workPool(maxPool int) {
var wg sync.WaitGroup
for i:=0;i<maxPool;i++{
wg.Add(1)
go worker(&wg)
}
wg.Wait()
close(resultChan)
}
func printResult() {
for res:=range resultChan{
fmt.Printf("任务id:%d随机数是:%d,的结果是:%d\n",res.Job.Id, res.Job.RoundNum, res.total)
}
}
func main() {
start :=time.Now()
go genNum(100)
go printResult()
workPool(10)
end:=time.Now()
fmt.Printf("运行时间%v\n", end.Sub(start))
}
defer
func mian(){
a :=10
defer func(a int) {
fmt.Println("defer执行匿名函数")
fmt.Println(a)
}(a)
a++
fmt.Println("执行结束")
}
异常处理
func test(s []int) {
defer func() {
if err:=recover();err!=nil{
fmt.Println(err)
}
}()
fmt.Println(s)
panic("主动抛出异常")
}
func main() {
s :=[]int{1,3,4}
test(s)
fmt.Println("执行主任务")
}
defer func(){
if err :=recover();err !=nil{
}
}()
fmt.Errorf("创建一个异常")
errors.New("创建一个异常")
type error interface {
Error() string
}
type myErr struct {
s string
}
func (e *myErr)Error() string {
return fmt.Sprintf("错误是%s",e.s)
}
func getCircleArea(r float32) (float32,error) {
if r<=0{
return 0,myErr{s:"半径不能小于0"}
}
return 3.14 * r * r,nil
}