tags:
categories:
package main
import(
"fmt"
"strconv"
"time"
)
func test(){
for i:=0; i < 10; i++{
fmt.Println("test() hello, world" + strconv.Itoa(i))
time.Sleep(time.Second)
}
}
func main(){
go test()
for i:=0; i < 10; i++{
fmt.Println("test() hello, Golang mian" + strconv.Itoa(i))
time.Sleep(time.Second)
}
}
package main
import(
"fmt"
"runtime"
)
func main(){
//获取当前系统逻辑cpu的数量
num := runtime.NumCPU()
//GOMAXPROCS设置可同时执行的最大CPU数,并返回先前的设置
runtime.GOMAXPROCS(num)
fmt.Println("num=", num)
}
package main
import(
"fmt"
"time"
)
// 定义一个全局map
var(
myMap = make(map[int]int, 10)
)
// 计算n!结果以及之前结果保存在myMap中
func test(n int){
res := 1
for i := 1; i <= n; i++{
res *= i
}
// 将结果储存在myMap中
myMap[n] = res
}
func main(){
for i := 1; i < 20; i++{
go test(i)
}
// 休眠10秒 防止主线程退出 其他协程也退出
time.Sleep(time.Second*10)
// 输出变量结果
for i, v := range myMap{
fmt.Printf("map[%d]=%d\n", i, v)
}
}
package main
import(
"fmt"
"time"
"sync"
)
// 定义一个全局map
var(
myMap = make(map[int]int, 10)
// 声明一个全局的互斥锁 lock是一个全局的互斥锁
lock sync.Mutex
)
// 计算n!结果以及之前结果保存在myMap中
func test(n int){
res := 1
for i := 1; i <= n; i++{
res *= i
}
// 将结果储存在myMap中
// 加锁
lock.Lock()
myMap[n] = res
lock.Unlock()
}
func main(){
for i := 1; i < 20; i++{
go test(i)
}
// 休眠10秒 防止主线程退出 其他协程也退出
time.Sleep(time.Second*10)
// 输出变量结果
// 主线程并不知道10秒能执行完成,因此底层可能仍然出现资源争夺,因此加入互斥锁即可解决问题
lock.Lock()
for i, v := range myMap{
fmt.Printf("map[%d]=%d\n", i, v)
}
lock.Unlock()
}
package main
import(
"fmt"
)
func main(){
//1.创建一个可以存放3个int类型的管道
var intChan chan int
intChan = make(chan int, 3)
fmt.Printf("intChan的值=%v intChan本身的地址=%p\n", intChan, &intChan)
// 2. 向管道中写入数据
intChan <- 10
num := 30
intChan <- num
intChan <- 40
// intChan <- 50 //不能超过最大长度 会报错all goroutines are asleep - deadlock!
//3.看看管道的长度和cap(容量)
fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan))
//4. 从管道中读取数据
num1 := <-intChan
num2 := <-intChan
num3 := <-intChan
//num4 := <-intChan 如果管道中无值再取 报错all goroutines are asleep - deadlock!
fmt.Println("num4:", num4)
fmt.Println("num1:", num1, "num2:", num2,"num3:", num3)
}
package main
import(
"fmt"
)
type Cat struct{
Name string
Age int
}
func main(){
// 创建一个map管道
var mapChan chan map[string]string
mapChan = make(chan map[string]string, 5)
m1 := make(map[string]string, 10)
m2 := make(map[string]string, 20)
m1["city1"] = "北京"
m1["city2"] = "上海"
m2["hero1"] = "松江"
m2["hero2"] = "红孩儿"
mapChan<- m1
mapChan<- m2
//可以直接从管道中扔出
<- mapChan
<- mapChan
fmt.Printf("Map管道%v\nm1的内容%v\nm2的内容%v\n", mapChan, m1, m2)
// 创建一个catChan,最多可以存放10个Cat结构体变量,演示写入和读取
var catChan chan Cat
catChan = make(chan Cat, 10)
cat1 := Cat{Name:"Tom", Age:18}
cat2 := Cat{Name:"Tom~", Age:23}
catChan<- cat1
catChan<- cat2
cat11 := <-catChan
cat22 := <-catChan
fmt.Printf("cat11的内容%v\ncat22的内容%v\n", cat11, cat22)
// 创建一个catChan2, 最多可以存放10个*Cat变量,演示写入和读取的用法
var catChan2 chan *Cat
catChan2 = make(chan *Cat, 10)
catChan2<- &cat1
catChan2<- &cat2
cat_1 := <-catChan2
cat_2 := <-catChan2
fmt.Println(cat_1, cat_2)
// 创建一个allChan,最多可以存放10个任意数据类型变量,演示写入和读取的用法
var allChan chan interface{}
allChan = make(chan interface{}, 10)
allChan<- cat1
allChan<- cat2
allChan<- 10
allChan<- "jack"
cat1_all := <- allChan
cat2_all := <- allChan
num_all := <-allChan
str_all := <-allChan
fmt.Println(cat1_all, cat2_all, num_all, str_all)
// 注意下面会报错 interface {} is interface with no methods
// 在编译层面它认为cat2_all是空接口类型
//fmt.Println(cat2_all.Name)
// 可以用类型断言即可
a := cat2_all.(Cat)
fmt.Println(a.Name)
}
package main
import(
"fmt"
)
func main(){
intchan := make(chan int, 3)
intchan <- 10
intchan <- 20
// 关闭管道
close(intchan)
// 关闭后不能在存放
// intchan <- 30
// 读取数据完全没有问题
n1 := <-intchan
<- intchan
fmt.Println(n1)
intchan2 := make(chan int, 100)
for i := 0; i < 100; i++{
intchan2<- i*2
}
// 遍历管道不能使用普通的for循环 因为一个取出后第二个就变成第一个位置啦
// for i := 0; i < len(intChan2); i++ {
// }
// 遍历前需要先关闭管道
close(intchan2)
for v := range intchan2{
fmt.Println(v)
}
}
package main
import(
"fmt"
"time"
)
// 写数据
func writeData(intChan chan int){
for i := 1; i <= 500; i++{
intChan<- i
fmt.Println("写入管道数据:", i)
}
close(intChan)
}
func readData(intChan chan int, exitChan chan bool){
for {
v, ok := <-intChan
if !ok{
break
}
// 频率不一样完全没问题
//time.Sleep(time.Second)
fmt.Println("读到管道数据:", v)
}
exitChan<- true
close(exitChan)
}
func main(){
// 创建两个管道
intChan := make(chan int, 50)
exitChan := make(chan bool, 1)
// 启动 写读协程
go writeData(intChan)
go readData(intChan, exitChan)
// 不停读取退出管道, 解决之前不知道何时协程执行完成的问题
for {
// 直到可以读到exitChan的值
_, ok := <-exitChan
// fmt.Println(ok) 这里!ok和ok是一样的结果
// 因为!ok指的取到后再取一次取不到, ok是直接取到(更直接)
if !ok{
break
}
}
}
package main
import(
"fmt"
"time"
)
func putNum(intChan chan int){
for i := 1; i <= 20000; i++{
intChan<- i
}
close(intChan)
}
// 取值判断是否为素数
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool){
var flag bool
for{
//time.Sleep(time.Millisecond * 10)
num, ok :=<- intChan
if !ok{
break
}
flag = true
// 判断是不是素数
for i := 2; i < num; i++{
if num % i == 0{
flag = false
break
}
}
if flag{
primeChan<- num
}
}
fmt.Printf("有协程已经取不到数据啦, 退出")
exitChan<- true
}
func main(){
intChan := make(chan int, 20000)
primeChan := make(chan int, 10000)
exitChan := make(chan bool, 4)
// 统计用时
start := time.Now().Unix()
// 开启一个协程放入1-8000个数
go putNum(intChan)
// 开启四个协程取出数据判断素数
for i := 0; i < 4; i++{
go primeNum(intChan, primeChan, exitChan)
}
// 再开一个协程 等待标志管道取出四个值
go func(){
for i := 0; i < 4; i++{
<- exitChan
}
// 取出后关闭管道primeChan
close(primeChan)
}()
// 遍历我们的primeChan把结果取出
for {
res, ok := <-primeChan
if !ok{
break
}
fmt.Printf("素数%d\n", res)
}
end := time.Now().Unix()
fmt.Printf("用时:%v", end - start)
}
package main
import(
"fmt"
)
func main(){
//管道可以声明为只读或者只写
//1.在默认情况下下,管道是双向
//var chan1 chan int //可读可写
//2.声明为只写
var chan2 chan<- int
chan2 = make(chan int, 3)
chan2<- 20
//num := <-chan2 //error
fmt.Println("chan2=", chan2)
//3.声明为只读 代码上没问题 但是没办法写怎么读 会报错
var chan3 <-chan int
num2 := <- chan3
//chan3<- 30 //err
fmt.Println("num2", num2)
}
package main
import(
"fmt"
"time"
)
func main(){
//使用select可以解决从管道取数据的阻塞问题
//1.定义一个管道10个数据int
intChan := make(chan int, 10)
for i := 0;i < 10; i++{
intChan<- i
}
// 2. 定义一个stringChan 存放5个string数据
stringChan := make(chan string, 5)
for i := 0;i < 5; i++{
stringChan<- "hello" + fmt.Sprintf("%d", i)
}
//传统的方法在遍历管道时,如果不关闭会阻塞而导致deadlock
//问题,在实际开发中,可能我们不好确定什么关闭该管道.
//可以使用select方式可以解决
//label:
for{
select{
//注意:这里,如果intChan一直没有关闭,不会一直阻塞而deadlock
//,会自动到下一个case匹配
case v := <-intChan :
fmt.Printf("从intChan读取的数据%d\n", v)
time.Sleep(time.Second)
case v := <-stringChan :
fmt.Printf("从stringChan读取的数据%s\n", v)
time.Sleep(time.Second)
default:
fmt.Printf("都取不到了, 不玩了, 程序员可以加入逻辑\n")
time.Sleep(time.Second)
return
//break label
}
}
}
package main
import(
"fmt"
"time"
)
func sayHello(){
for i := 1; i <= 10; i++{
time.Sleep(time.Second)
fmt.Println("hello world sayHello", i)
}
}
func test(){
//这里我们可以使用defer + recover
defer func(){
//捕获test拋出的panic
if err := recover(); err != nil{
fmt.Println("test() 发生错误", err)
}
}()
var myMap map[int]string
// 没有make 就是用 肯定报错 看报错会不会终止主线程
myMap[0] = "golang"
}
func main(){
go sayHello()
go test()
for i := 0; i <= 10; i++{
fmt.Println("main ok", i)
time.Sleep(time.Second)
}
}