Go语言入门心法(八): mysql驱动安装报错onnection failed
Go语言入门心法(十):Go语言操作MYSQL(CRUD)|事务处理
并行与并发认知升维:
go语言中协程与并发认知
(1) go语言的最大特点,是从语言层面支持并发
(2) Go语言的最大优势在于并发与性能,其性能可以媲美C和C++,并发在网络编程中更是至关重要
(3) 有事光靠硬件的提升无法满足高并发的需求的,因此需从程序的角度来解决高并发问题
(4) 通常并发指在同一段时间内,程序可以执行多个任务;几乎所有的语言都支持并发,而go语言最大的特点就是从语言层面支持并发
(5) 并发编程通常包括: 多线程编程,多进程编程,一家分布式编程
(6) 调用栈: 调用栈是计算机科学中存储有关正在运行的子程序的消息栈,经常被用于存放子程序的返回地址。在调用任何子程序中,主程序都必须暂存子程序运行完毕后应该返回到的地址。
因此,如果被调用的子程序还要调用其他子程序,其自身的返回地址必须存入调用栈,在其自身运行完毕后再取回。
(7) 并发与并行区别
7.1: 并行(parallelism):指在同一时刻,有多条指令在多个处理器上同时运行
7.2: 并发(concurrency):指在同一时刻,只能有一条指令执行,但是多个进程指令被快速第轮换执行,得到宏观上有多个进程同时执行的效果,
但是在微观上并不是同时执行,只是把时间片分为了若干段,使得多个进程快速交替执行。
一: go语言并发与通道
package main
import (
"fmt"
"time"
)
/*
go语言中协程与并发认知
(1) go语言的最大特点,是从语言层面支持并发
(2) Go语言的最大优势在于并发与性能,其性能可以媲美C和C++,并发在网络编程中更是至关重要
(3) 有时光靠硬件的提升无法满足高并发的需求的,因此需从程序的角度来解决高并发问题
(4) 通常并发指在同一段时间内,程序可以执行多个任务;几乎所有的语言都支持并发,而go语言最大的特点就是从语言层面支持并发
(5) 并发编程通常包括: 多线程编程,多进程编程,分布式编程
(6) 调用栈: 调用栈是计算机科学中存储有关正在运行的子程序的消息栈,经常被用于存放子程序的返回地址。在调用任何子程序中,主程序都必须暂存子程序运行完毕后应该返回到的地址。
因此,如果被调用的子程序还要调用其他子程序,其自身的返回地址必须存入调用栈,在其自身运行完毕后再取回。
(7) 并发与并行区别
7.1: 并行(parallelism):指在同一时刻,有多条指令在多个处理器上同时运行
7.2: 并发(concurrency):指在同一时刻,只能有一条指令执行,但是多个进程指令被快速第轮换执行,得到宏观上有多个进程同时执行的效果,
但是在微观上并不是同时执行,只是把时间片分为了若干段,使得多个进程快速交替执行。
*/
func main() {
println(`
go语言中协程与并发认知
(1) go语言的最大特点,是从语言层面支持并发
(2) Go语言的最大优势在于并发与性能,其性能可以媲美C和C++,并发在网络编程中更是至关重要
(3) 有时光靠硬件的提升无法满足高并发的需求的,因此需从程序的角度来解决高并发问题
(4) 通常并发指在同一段时间内,程序可以执行多个任务;几乎所有的语言都支持并发,而go语言最大的特点就是从语言层面支持并发
(5) 并发编程通常包括: 多线程编程,多进程编程,分布式编程
(6) 调用栈: 调用栈是计算机科学中存储有关正在运行的子程序的消息栈,经常被用于存放子程序的返回地址。在调用任何子程序中,主程序都必须暂存子程序运行完毕后应该返回到的地址。
因此,如果被调用的子程序还要调用其他子程序,其自身的返回地址必须存入调用栈,在其自身运行完毕后再取回。
(7) 并发与并行区别
7.1: 并行(parallelism):指在同一时刻,有多条指令在多个处理器上同时运行
7.2: 并发(concurrency):指在同一时刻,只能有一条指令执行,但是多个进程指令被快速第轮换执行,得到宏观上有多个进程同时执行的效果,
但是在微观上并不是同时执行,只是把时间片分为了若干段,使得多个进程快速交替执行。
在go语言中,编写并发程序时非常简单的,它不需要引入第三方额外的库,创建goroutine,只需要在函数调用语句前面添加go关键字,
就可以创建并行执行单元。开发人员无须了解任何执行细节,调度器会自动将其安排到合适的线程上去执行;
在并发编程里,通常要将一个过程分割成几块,然后让不同的goroutine各自负责其中的一块工作;
`)
println("该程序有三个模块,分别是main,Task1,Task2,这里使用了两个关键字go将task1和task2改变成了两个并的模块")
println()
go goroutineTask1()
go goroutineTask2()
for {
fmt.Println(time.Now().Format("15:04:05"), "正在处理主进程的任务")
time.Sleep(time.Second * 3)
}
}
// goroutineTask1 定义任务执行函数
func goroutineTask1() {
for {
fmt.Println(time.Now().Format("15:04:05"), "正在执行Task1任务")
time.Sleep(time.Second * 1) // 休眠1秒
}
}
// goroutineTask2 定义任务执行函数
func goroutineTask2() {
for {
fmt.Println(time.Now().Format("15:04:05"), "正在执行Task2任务")
time.Sleep(time.Second * 2) // 休眠1秒
}
}
运行效果:
D:\program_file_worker\go1.20 #gosetup
GOPATH=D:\program_file_worker\go1.20\bin;C:\Users\Administrator\go #gosetup
D:\program_file_worker\go1.20\bin\go.exe build -o C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_OOPGoroutineToChannelGrammar_go.exe D:\program_file\go_workspace\org.jd.data\goroutine\OOPGoroutineToChannelGrammar.go #gosetup
C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_OOPGoroutineToChannelGrammar_go.exego语言中协程与并发认知
(1) go语言的最大特点,是从语言层面支持并发
(2) Go语言的最大优势在于并发与性能,其性能可以媲美C和C++,并发在网络编程中更是至关重要(3) 有时光靠硬件的提升无法满足高并发的需求的,因此需从程
序的角度来解决高并发问题
(4) 通常并发指在同一段时间内,程序可以执行多个任务;几乎所有的语言都支持并发,而go语言最大的特点就是从语言层面支持并发(5) 并发编程通常包括: 多线程编程,多进程编程,分布式编程
的消息栈,经常被用于存放子程序的返回地址。在调用任何子程序中,主程序都必须暂存子程序运行完毕后应该返回到的地址。
的消息栈,经常被用于存放子程序的返回地址。在调用任何子程序中,主程序都必须暂存子程序运行完毕后应该返回到的地址。
因此,如果被调用的子程序还要调用其他子程序,其自身的返回地址必须存入调用栈,在其自身运行完毕后再取回。
(7) 并发与并行区别
7.1: 并行(parallelism):指在同一时刻,有多条指令在多个处理器上同时运行
7.2: 并发(concurrency):指在同一时刻,只能有一条指令执行,但是多个进程指令被快速第轮换执行,得到宏观上有多个进程同时执行的效果,
但是在微观上并不是同时执行,只是把时间片分为了若干段,使得多个进程快速交替执行。
在go语言中,编写并发程序时非常简单的,它不需要引入第三方额外的库,创建goroutine,只需要在函数调用语句前面添加go关键字,
就可以创建并行执行单元。开发人员无须了解任何执行细节,调度器会自动将其安排到合适的线程上去执行;
在并发编程里,通常要将一个过程分割成几块,然后让不同的goroutine各自负责其中的一块工作;该程序有三个模块,分别是main,Task1,Task2,这里使用了两个关键字go将task1和task2改变成了两个并的模块
21:31:14 正在处理主进程的任务
21:31:14 正在执行Task1任务
21:31:14 正在执行Task2任务21:31:16 正在执行Task1任务
21:31:17 正在执行Task1任务
21:31:17 正在执行Task2任务
21:31:18 正在处理主进程的任务
21:31:18 正在执行Task1任务
21:31:19 正在执行Task2任务
21:31:19 正在执行Task1任务
21:31:20 正在执行Task1任务
21:31:21 正在处理主进程的任务
21:31:21 正在执行Task2任务
21:31:21 正在执行Task1任务Process finished with the exit code -1073741510 (0xC000013A: interrupted by Ctrl+C)
二: 主|子协程认知
goroutine(协程两种创建方式):
(1) 关键字 go 被调用的函数名称(参数列表)
(2) 匿名函数创建协程(goroutine): 关键字go后面可以为匿名函数,格式如下所示:
go func(参数列表) {
函数体
}(调用参数列表)
(3)当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们称之为main goroutine
package main
import (
"fmt"
"time"
)
/*
goroutine(协程两种创建方式):
(1) 关键字 go 被调用的函数名称(参数列表)
(2) 匿名函数创建协程(goroutine): 关键字go后面可以为匿名函数,格式如下所示:
go func(参数列表) {
函数体
}(调用参数列表)
(3)当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们称之为main goroutine
*/
func main() {
go Task1()
println(`
main函数: 当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们称之为main goroutine,
新的goroutine会使用go关键字来创建来创建
`)
}
func Task1() {
for {
fmt.Println(time.Now().Format("15:04:05"), "正在处理Task1的任务......")
time.Sleep(time.Second * 3)
}
}
运行效果:发现子协程没有执行,这是因为运行go Task1(),程序会立刻返回到main函数,而执行完主协程中println函数后,发现没有执行的代码,程序就会判断执行完毕,终止所有的协程;要让子协程也执行,需要在主协程中添加一些等待逻辑;
=D:\program_file_worker\go1.20 #gosetup
GOPATH=D:\program_file_worker\go1.20\bin;C:\Users\Administrator\go #gosetup
D:\program_file_worker\go1.20\bin\go.exe build -o C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_OOPGoroutineToMultiGoroutineGrammar_go.exe D:\program_file\go_workspace\org.jd.data\goroutine\OOPGoroutineToMultiGoroutineGrammar.go #gosetup
C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_OOPGoroutineToMultiGoroutineGrammar_go.exemain函数: 当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们称之为main goroutine,
新的goroutine会使用go关键字来创建来创建
Process finished with the exit code 0
添加等待逻辑代码:
func main() {
go Task1()
println(`
main函数: 当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们称之为main goroutine,
新的goroutine会使用go关键字来创建来创建
`)
time.Sleep(time.Second * 100)
}
在次运行效果:
GOROOT=D:\program_file_worker\go1.20 #gosetup
GOPATH=D:\program_file_worker\go1.20\bin;C:\Users\Administrator\go #gosetup
D:\program_file_worker\go1.20\bin\go.exe build -o C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_OOPGoroutineToMultiGoroutineGrammar_go.exe D:\program_file\go_workspace\org.jd.data\goroutine\OOPGoroutineToMultiGoroutineGrammar.go #gosetup
C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_OOPGoroutineToMultiGoroutineGrammar_go.exemain函数: 当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们称之为main goroutine,
新的goroutine会使用go关键字来创建来创建11:41:27 正在处理Task1的任务......
11:41:30 正在处理Task1的任务......
11:41:33 正在处理Task1的任务......
11:41:36 正在处理Task1的任务......
11:41:39 正在处理Task1的任务......
11:41:42 正在处理Task1的任务......
三: 主|子协程协同运行Gosched()
runtime包
Go语言中runtime(运行时)包实现了一个小型的任务调度器。这个调度器的工作原理和系统对线程调度的原理类似,
Go语言调度器可以高效地将CPU资源分配给每一个任务;其中包含三个重要的函数
(1) Gosched()该函数是使当前go协程放弃处理器,以让其他的go协程运行。不会挂起当前go协程,因此当前go协程未来会恢复执行;
package main
import (
"fmt"
"runtime"
)
/*
runtime包
Go语言中runtime(运行时)包实现了一个小型的任务调度器。这个调度器的工作原理和系统对线程调度的原理类似,
Go语言调度器可以高效地将CPU资源分配给每一个任务;其中包含三个重要的函数
(1) Gosched()该函数是使当前go协程放弃处理器,以让其他的go协程运行。不会挂起当前go协程,因此当前go协程未来会恢复执行;
*/
func main() {
println("匿名的方式创建一个协程任务")
go func() {
for i := 0; i < 5; i++ {
fmt.Println("子协程:", "go start ")
}
}()
for i := 0; i < 2; i++ {
// 通过协程调度器来让出当前的CUP,让子协程运行后,在运行主协程
runtime.Gosched()
fmt.Println("主协程:", "main start ")
}
}
运行效果: 该效果也可以通过在主协中添加 time.Sleep(time.Second * 3) 逻辑,但是执行顺序不一定能是先子协程,再主携程的顺序;
GOROOT=D:\program_file_worker\go1.20 #gosetup
GOPATH=D:\program_file_worker\go1.20\bin;C:\Users\Administrator\go #gosetup
D:\program_file_worker\go1.20\bin\go.exe build -o C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_org_jd_data_org_jd_data_goroutine.exe D:\program_file\go_workspace\org.jd.data\goroutine\OOPGoroutineToMultiGoroutineRuntimeGrammar.go #gosetup
C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_org_jd_data_org_jd_data_goroutine.exe
匿名的方式创建一个协程任务
子协程: go start
子协程: go start
子协程: go start
子协程: go start
子协程: go start
主协程: main start
主协程: main startProcess finished with the exit code 0
四: 某协程提前终止操作函数Goexit()
runtime包
Go语言中runtime(运行时)包实现了一个小型的任务调度器。这个调度器的工作原理和系统对线程调度的原理类似,
Go语言调度器可以高效地将CPU资源分配给每一个任务;其中包含三个重要的函数
(1) Gosched()该函数是使当前go协程放弃处理器,以让其他的go协程运行。不会挂起当前go协程,因此当前go协程未来会恢复执行;
(2) Goexit() 该函数功能: 终止调用它自己的go协程,但其他协程不会受到影响;Goexit函数会在终止该go协程前执行所有的defer的函数
package main
import (
"fmt"
"runtime"
"time"
)
/*
runtime包
Go语言中runtime(运行时)包实现了一个小型的任务调度器。这个调度器的工作原理和系统对线程调度的原理类似,
Go语言调度器可以高效地将CPU资源分配给每一个任务;其中包含三个重要的函数
(1) Gosched()该函数是使当前go协程放弃处理器,以让其他的go协程运行。不会挂起当前go协程,因此当前go协程未来会恢复执行;
(2) Goexit() 该函数功能: 终止调用它自己的go协程,但其他协程不会受到影响;Goexit函数会在终止该go协程前执行所有的defer的函数
*/
func main() {
go task1()
go task2()
time.Sleep(time.Second * 5)
}
func task1() {
defer fmt.Println("task1 stop")
fmt.Println("task1 start")
fmt.Println("task1 work")
}
func task2() {
defer fmt.Println("task2 stop")
fmt.Println("task2 start")
runtime.Goexit() // 效果与return 一样
fmt.Println("task2 work")
运行效果:
GOROOT=D:\program_file_worker\go1.20 #gosetup
GOPATH=D:\program_file_worker\go1.20\bin;C:\Users\Administrator\go #gosetup
D:\program_file_worker\go1.20\bin\go.exe build -o C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_org_jd_data_org_jd_data_goroutine__1_.exe D:\program_file\go_workspace\org.jd.data\goroutine\OOPGoroutineToMultiGoroutineGoexitGrammar.go #gosetup
C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_org_jd_data_org_jd_data_goroutine__1_.exe
task1 start
task1 work
task1 stop
task2 start
task2 stopProcess finished with the exit code 0
从运行结果中可以看出,task2 work并没有输出,在调用了runtime.Goexit()函数后,该协程余下的代码不会被执行,相当于在调用Goexit()函数的位置执行return语句一样
五: 设置程序运行的CUP数
runtime包
Go语言中runtime(运行时)包实现了一个小型的任务调度器。这个调度器的工作原理和系统对线程调度的原理类似,
Go语言调度器可以高效地将CPU资源分配给每一个任务;其中包含三个重要的函数
(1) Gosched()该函数是使当前go协程放弃处理器,以让其他的go协程运行。不会挂起当前go协程,因此当前go协程未来会恢复执行;
(2) Goexit() 该函数功能: 终止调用它自己的go协程,但其他协程不会受到影响;Goexit函数会在终止该go协程前执行所有的defer的函数
(3) GOMAXPROCS()函数可以设置程序在运行中所使用的CPU数,在以后的编程中使用得最大的函数之一,Go语言程序默认会使用最大CUP进行计算
func GOMAXPROCS(n int) int
package main
import (
"fmt"
"runtime"
"time"
)
/*
runtime包
Go语言中runtime(运行时)包实现了一个小型的任务调度器。这个调度器的工作原理和系统对线程调度的原理类似,
Go语言调度器可以高效地将CPU资源分配给每一个任务;其中包含三个重要的函数
(1) Gosched()该函数是使当前go协程放弃处理器,以让其他的go协程运行。不会挂起当前go协程,因此当前go协程未来会恢复执行;
(2) Goexit() 该函数功能: 终止调用它自己的go协程,但其他协程不会受到影响;Goexit函数会在终止该go协程前执行所有的defer的函数
(3) GOMAXPROCS()函数可以设置程序在运行中所使用的CPU数,在以后的编程中使用得最大的函数之一,Go语言程序默认会使用最大CUP进行计算
func GOMAXPROCS(n int) int
*/
func main() {
n := runtime.GOMAXPROCS(1)
fmt.Println("先前的CPU核数设置为: ", n)
last := time.Now()
for i := 0; i < 100000; i++ {
go func() {
// 耗时任务
a := 999999 ^ 999999
a = a + 1
}()
}
now := time.Now()
fmt.Println(now.Sub(last))
}
1个CUP运行效果:
C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_org_jd_data_org_jd_data_goroutine__2_.exe
先前的CPU核数设置为: 20
152.5748msProcess finished with the exit code 0
设置4个CUP运行的效果:
先前的CPU核数设置为: 20
40.3461msProcess finished with the exit code 0