Go管道注意细节

Posted yzg-14

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go管道注意细节相关的知识,希望对你有一定的参考价值。

技术图片

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) //chan2= 0xc000094000

	//3. 声明为只读
	var chan3 <-chan int
	fmt.Println("chan3", chan3) //chan3 <nil>
	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
	}
	fmt.Printf("%v
", intChan) //0xc00007a000

	//2.定义一个管道 5个数据string
	stringChan := make(chan string, 5)
	for i := 0; i < 5; i++ {
		stringChan <- "hello" + fmt.Sprintf("%d", i)
	}
	fmt.Printf("%v
", stringChan)

	//传统的方法在遍历管道时,如果不关闭会阻塞而导致 deadlock
	//for {
	//	v := <-intChan
	//	fmt.Printf("从intChan读取的数据%d
", v)
	//}
	//问题,在实际开发中,可能我们不好确定什么关闭该管道.
	//可以使用select 方式可以解决
	//label:
	for {
		select {
		//注意: 这里,如果intChan一直没有关闭,不会一直阻塞而deadlock,会自动到下一个case匹配
		case v := <-intChan:
			fmt.Printf("从intChan读取的数据%d
", v)
			//time.Sleep(time.Second)
		case v := <-stringChan:
			fmt.Printf("从stringChan读取的数据%s
", v)
			//time.Sleep(time.Second)
		default: //都取不到
			fmt.Printf("都取不到了,不玩了, 程序员可以加入逻辑
")
			//time.Sleep(time.Second)
			return
			//break //只能跳到select
			//break label //跳到第一个lable标签那去
		}
	}
}
//=========顺序无法控制=============

//0xc000092000
//0xc000098000
//从intChan读取的数据0
//从intChan读取的数据1
//从intChan读取的数据2
//从intChan读取的数据3
//从stringChan读取的数据hello0
//从stringChan读取的数据hello1
//从intChan读取的数据4
//从stringChan读取的数据hello2
//从stringChan读取的数据hello3
//从intChan读取的数据5
//从stringChan读取的数据hello4
//从intChan读取的数据6
//从intChan读取的数据7
//从intChan读取的数据8
//从intChan读取的数据9
//都取不到了,不玩了, 程序员可以加入逻辑

技术图片

package main
import (
	"fmt"
	_ "time"
)

//函数
func sayHello() {
	for i := 0; i < 10; i++ {
		//time.Sleep(time.Second)
		fmt.Println("hello,world")
	}
}


//函数
func test() {
	//这里我们可以使用defer + recover
	defer func() {
		//捕获test这个函数(多协程时,这个协程)抛出的panic
		if err := recover(); err != nil {
			fmt.Println("test() 发生错误", err)
		}
	}()
	//定义了一个map
	var myMap map[int]string
	myMap[0] = "golang" // 这里会报错
}

func main() {

	go sayHello()
	go test()


	for i := 0; i < 10; i++ {
		fmt.Println("main() ok=", i)
		//time.Sleep(time.Second)
	}

} 

技术图片

 

以上是关于Go管道注意细节的主要内容,如果未能解决你的问题,请参考以下文章

go语言中数组使用的注意事项和细节

go map 需要注意的细节

go map 需要注意的细节

go map 需要注意的细节

go map 需要注意的细节

Golang并发(Go程管道)