Golang channle管道的基本使用及快速入门

 更新时间:2023年12月19日 10:43:21   作者:富士康质检员张全蛋  
管道是Go语言中实现并发的一种方式,它可以在多个goroutine之间进行通信和数据交换,本文主要介绍了Golang channle管道的基本使用及快速入门,具有一定的参考价值,感兴趣的可以了解一下

channel(管道)-基本介绍

为什么需要channel?前面使用全局变量加锁同步来解决goroutine的通讯,但不完美

(1)主线程在等待所有goroutine全部完成的时间很难确定,我们这里设置10秒,仅仅是估算。
(2)如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能还有goroutine处于工作状态,这时也会随主线程的退出而销毁。
(3)通过全局变量加锁同步来实现通讯,也并不利用多个协程对全局变量的读写操作。
(4)上面种种分析都在呼唤一个新的通讯机制channel

import (
	"fmt"
	"sync"
	"time"
)

var (
	m = make(map[int]int, 10)
	//声明一个全局的互斥锁  lock是一个全局的互斥锁
	//sync是包  同步的意思  mutex是互斥的意思
	lock sync.Mutex
)

// test函数就是计算n的阶乘
func test(n int) {
	res := 1
	for i := 1; i <= n; i++ {
		res = res * i
	}
	//将计算结果放到map当中 加锁
	lock.Lock()
	m[n] = res
	lock.Unlock()
}

func main() {
	//这里开启多协程完成任务
	for i := 1; i <= 20; i++ {
		go test(i)
	}

	time.Sleep(time.Second * 10)
	for k, v := range m {
		fmt.Println(k, v)
	}
}

channel的介绍

(1)channle本质就是一个数据结构-队列,数据是先进先出
(2)线程安全,多goroutine访问时,不需要加锁,就是说channel本身就是线程安全的(管道是线程安全的,你在对管道读取的时候不管有多少个协程在对同一个管道操作,可以放心使用,不会出现错误,这些是有编译器在底层维护的)
(3)channel是有类型的,一个string的channel只能存放string类型数据。(如果管道想放int或者float那么可以使用空接口interface类型)

定义/声明channel nil类型

var 变量名 chan 数据类型,举例:

var intChan chan int (intChan用于存放int数据)
var mapChan chan map[int]string  (mapChan用于存放map[int]string类型)
var perChan chan Person
var perChan2 chan *Person

说明:

(1)channel是引用类型

(2)channel必须初始化才能写入数据,即make后才能使用

(3)管道是有类型的,intChan只能写入整数int

channel初始化

说明:使用make进行初始化

var intChan chan int
intChan =make(chan int,10)

向channel中写入(存放)数据

var intChan chan int
intChan = make(chan int,10)
num = 999
intChan <- 10
intChan <- num

如果将channel传给另外一个函数,那么在这个函数里面操作的是同一个管道,因为它是引用类型。

package main

import "fmt"

func main() {
	var intChan chan int
	//创建可以存放3个int类型的管道
	intChan = make(chan int, 3)

	//看看intChan是什么
	fmt.Printf("initChan的值为=%v\n initChan本身地址为%p\n", intChan, &intChan)

	//向管道写入数据
	intChan <- 1
	num := 2
	intChan <- num
	//当给管道写入数据的时候,不能超过其容量
	//看看管道的长度和cap
	fmt.Println("长度:", len(intChan), "容量:", cap(intChan))

	num1 := <-intChan
	fmt.Println("取出来的第一个数据是:", num1)
	fmt.Println("取出之后的长度:", len(intChan), "取出之后的容量:", cap(intChan))
	//在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告deadlock
}


initChan的值为=0xc00007a080
initChan本身地址为0xc00000a028
长度: 2 容量: 3                    
取出来的第一个数据是: 1            
取出之后的长度: 1 取出之后的容量: 3

要将什么样的数据放到管道里面呢?就是这种数据是流动的,它一边往里面放,另外一边去读取,这样通信机制就形成了。<-ch这种接受方式也可以,将数据丢掉,数据不想要,这也是取的一种方式,只不过不想要。

 channel 使用注意事项

(1)channel中只能存放指定的数据类型

(2)channle的数据放满后,就不能再放入了(会出现死锁的错误),如果从channel取出数据后,可以继续放入

(3)在没有使用协程的情况下,如果channel数据取完了,再取,就会报dead lock

读写channel案例 

管道里面可以存放很多map,每个map里面又可以有多对的key/value。这里在使用map之前要先make一下 。

管道也是可以存放结构体实例的。

管道里面也可以存放指针。

如果希望在这个管道里面存放的是混合类型的数据,我们既想放结构体又想放字符串。这里的数据类型为空接口类型interface{},因为任何的数据类型都认为实现了空接口。

注意:取出来的时候记得使用类型断言。

package main

import (
	"fmt"
	"reflect"
)

type Cat struct {
	Name string
	Age  int
}

func main() {
	allChan := make(chan interface{}, 3)
	cat1 := Cat{
		Name: "1",
		Age:  10,
	}

	allChan <- "hello"
	allChan <- 1
	allChan <- cat1

	<-allChan
	<-allChan
	newCat := <-allChan
	fmt.Println(reflect.TypeOf(newCat))
	fmt.Printf("%T\n %#v\n", newCat, newCat)
	//fmt.Println(c.Name, c.Age) 这种写法是错误的,编译器通不过,使用类型断言即可
	c := newCat.(Cat)
	fmt.Println(c.Name, c.Age)
}

6)存放函数

ch := make(chan func(string) string, 10)
ch <- func(name string) string {  //使用匿名函数
	return "hello " + name
}

到此这篇关于Golang channle管道的基本使用及快速入门的文章就介绍到这了,更多相关Golang channle管道内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • golang判断文本文件是否是BOM格式的方法详解

    golang判断文本文件是否是BOM格式的方法详解

    在Go语言中,我们可以通过读取文本文件的前几个字节来识别它是否是BOM格式的文件,BOM(Byte Order Mark)是UTF编码标准中的一部分,用于标示文本文件的编码顺序,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • go内存缓存BigCache封装Entry源码解读

    go内存缓存BigCache封装Entry源码解读

    这篇文章主要为大家介绍了go内存缓存BigCache封装Entry源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Go语言接口定义与用法示例

    Go语言接口定义与用法示例

    这篇文章主要介绍了Go语言接口定义与用法,较为详细的分析了Go语言中接口的概念、定义、用法,需要的朋友可以参考下
    2016-07-07
  • 使用Go语言实现配置文件热加载功能

    使用Go语言实现配置文件热加载功能

    这篇文章主要介绍了使用Go语言实现配置文件热加载功能,以及配置文件热加载包的实现思路,需要的朋友可以参考下
    2018-03-03
  • goland 实现websocket server的示例代码

    goland 实现websocket server的示例代码

    本文主要介绍了goland 实现websocket server的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • go mod 使用私有gitlab群组的解决方案

    go mod 使用私有gitlab群组的解决方案

    这篇文章主要介绍了go mod 使用私有gitlab群组的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • 为什么Go里值为nil可以调用函数原理分析

    为什么Go里值为nil可以调用函数原理分析

    这篇文章主要为大家介绍了为什么Go里值为nil可以调用函数原理分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • go modules中replace使用方法

    go modules中replace使用方法

    这篇文章主要为大家介绍了go modules中replace使用方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 使用golang写一个redis-cli的方法示例

    使用golang写一个redis-cli的方法示例

    这篇文章主要介绍了使用golang写一个redis-cli的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 在Go语言单元测试中解决HTTP网络依赖问题

    在Go语言单元测试中解决HTTP网络依赖问题

    在 Go 语言中,我们需要找到一种可靠的方法来测试 HTTP 请求和响应,本文将探讨在 Go 中进行 HTTP 应用测试时,如何解决应用程序的依赖问题,以确保我们能够编写出可靠的测试用例,需要的朋友可以参考下
    2023-07-07

最新评论