首页 > 其他分享 >golang中各种状态下channel(管道)的读、写、close操作

golang中各种状态下channel(管道)的读、写、close操作

时间:2024-04-03 18:44:21浏览次数:22  
标签:struct chan golang func go close channel

一、简介

golang中各种状态下channel(管道)的读、写、close操作

二、结论

channel状态 close
close 零值 panic panic
nil 永久阻塞(deadlock) 永久阻塞(deadlock) panic
buffer满 正常 永久阻塞(deadlock) 正常
buffer空 永久阻塞(deadlock) 正常 正常

三、验证

创建两个go文件
管道状态文件:chan_state.go
测试文件:chan_state_test.go

命令行执行

go test -v

结果见第四部分

chan_state.go

package channel

import "fmt"

type BaseChan interface {
	Read()
	Write()
	Close()
}

type BasicActionChan struct {
	ch chan int
}

func (ch *BasicActionChan) Read() {
	value := <-ch.ch
	fmt.Println("read success", value)
}

func (ch *BasicActionChan) Write() {
	ch.ch <- 1
	fmt.Println("write success")
}

func (ch *BasicActionChan) Close() {
	close(ch.ch)
}

type CloseChan struct {
	BasicActionChan
}

func NewCloseChan() BaseChan {
	ch := &CloseChan{BasicActionChan{ch: make(chan int)}}
	close(ch.ch)
	return ch
}

type NilChan struct {
	BasicActionChan
}

func NewNilChan() BaseChan {
	ch := &NilChan{BasicActionChan{ch: nil}}
	return ch
}

type FullBufferChan struct {
	BasicActionChan
}

func NewFullBufferChan() BaseChan {
	ch := &FullBufferChan{BasicActionChan{ch: make(chan int, 1)}}
	ch.ch <- 1
	return ch
}

type EmptyBufferChan struct {
	BasicActionChan
}

func NewEmptyBufferChan() BaseChan {
	ch := &EmptyBufferChan{BasicActionChan{ch: make(chan int, 1)}}
	return ch
}

chan_state_test.go

package channel

import (
	"context"
	"fmt"
	"testing"
	"time"
)

type Case struct {
	Name   string
	Ch     BaseChan
	Action func(baseChan BaseChan)
}

func helper(t *testing.T, c *Case) {
	t.Helper()
	t.Run(c.Name, func(tt *testing.T) {
		ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
		defer cancel()
		done := make(chan struct{})
		panicCh := make(chan struct{})
		go func() {
			defer func() {
				if err := recover(); err != nil {
					fmt.Println("panic ", err)
					panicCh <- struct{}{}
				}
			}()
			c.Action(c.Ch)
			done <- struct{}{}
		}()
		select {
		case <-ctx.Done():
			fmt.Println("timeout ")
		case <-panicCh:

		case <-done:
			fmt.Println("success")
		}
	})
}

func TestNewCloseChan(t *testing.T) {
	helper(t, &Case{Name: "close chan read", Ch: NewCloseChan(), Action: func(baseChan BaseChan) {
		baseChan.Read()
	}})

	helper(t, &Case{Name: "close chan write", Ch: NewCloseChan(), Action: func(baseChan BaseChan) {
		baseChan.Write()
	}})

	helper(t, &Case{Name: "close chan close", Ch: NewCloseChan(), Action: func(baseChan BaseChan) {
		baseChan.Close()
	}})
}

func TestNewNilChan(t *testing.T) {
	helper(t, &Case{Name: "nil chan read", Ch: NewNilChan(), Action: func(baseChan BaseChan) {
		baseChan.Read()
	}})

	helper(t, &Case{Name: "nil chan write", Ch: NewNilChan(), Action: func(baseChan BaseChan) {
		baseChan.Write()
	}})

	helper(t, &Case{Name: "nil chan close", Ch: NewNilChan(), Action: func(baseChan BaseChan) {
		baseChan.Close()
	}})
}

func TestNewFullBufferChan(t *testing.T) {
	helper(t, &Case{Name: "full chan read", Ch: NewFullBufferChan(), Action: func(baseChan BaseChan) {
		baseChan.Read()
	}})

	helper(t, &Case{Name: "full chan write", Ch: NewFullBufferChan(), Action: func(baseChan BaseChan) {
		baseChan.Write()
	}})

	helper(t, &Case{Name: "full chan close", Ch: NewFullBufferChan(), Action: func(baseChan BaseChan) {
		baseChan.Close()
	}})
}

func TestNewEmptyBufferChan(t *testing.T) {
	helper(t, &Case{Name: "empty chan read", Ch: NewEmptyBufferChan(), Action: func(baseChan BaseChan) {
		baseChan.Read()
	}})

	helper(t, &Case{Name: "empty chan write", Ch: NewEmptyBufferChan(), Action: func(baseChan BaseChan) {
		baseChan.Write()
	}})

	helper(t, &Case{Name: "empty chan close", Ch: NewEmptyBufferChan(), Action: func(baseChan BaseChan) {
		baseChan.Close()
	}})
}

四、结果

标签:struct,chan,golang,func,go,close,channel
From: https://www.cnblogs.com/genechen/p/18113334

相关文章

  • golang—踩坑之切片
    1.记录一次切片引用错误,希望大家不要踩坑,用来惊醒自己!修改之前:import("context""encoding/json""feishu/global""feishu/structure""feishu/utils""fmt""github.com/gin-gonic/gin"......
  • golang中GORM使用 many2many 多对多关联查询-详细案例
    表结构和数据user表CREATETABLE`user`(`id`bigint(20)NOTNULL,`user_key`bigint(20)NOTNULL,`account`char(32)NOTNULL)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;为了测试将user_key和id写入同样的值数据:+----+----------+---------+|id|user_k......
  • Golang | Leetcode Golang题解之第4题寻找两个正序数组的中位数
    题目:题解:funcfindMedianSortedArrays(nums1[]int,nums2[]int)float64{iflen(nums1)>len(nums2){returnfindMedianSortedArrays(nums2,nums1)}m,n:=len(nums1),len(nums2)left,right:=0,mmedian1,median2:=0,0......
  • golang语言系列:Scrum、Kanban等敏捷管理策略
    云原生学习路线导航页(持续更新中)本文是golang语言系列文章,主要对编程通用技能Scrum、Kanban等敏捷管理策略进行学习1.什么是敏捷开发敏捷是一个描述软件开发方法的术语,它强调增量交付、团队协作、持续规划和持续学习。2001年,敏捷宣言提出:个体和交互胜过流程和......
  • python golang 安装私有库的用法
    python安装在requirements.txt增加了github私有安装库的依赖git+https://${GITHUB_TOKEN}@github.com/YOLOTECHNOLOGY/bossjob-auth-lib.git@${GITHUB_LIB_BRANCH}当前该库无法通过pipenv直接安装,需要进入到虚拟环境,通过pipinstall进行安装安装前需要设置GITHUB_......
  • 声道 Sound Channel
    声道(SoundChannel)是指声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号,所以声道数也就是声音录制时的音源数量或回放时相应的扬声器数量。https://baike.baidu.com/item/声道/2119484Stereo单声道缺乏对声音的位置定位,而立体声技术则彻底改变了这一状况。......
  • 安洵杯2023 side_channel , initiate!:侧信道爆破flag
    当程序有办法读取到flag但无法将flag输出出来时,可以采用侧信道爆破flag确定其内容。例题:安洵杯2023side_channel,initiate!题目本身很简单,允许在bss上写一大段,然后一个栈溢出。但沙箱是这个画风:函数里还有一个单纯的movrax0fh,允许了rt_stgreturn和mprotect的权限,很明显的提......
  • golang: 分析查看汇编代码
    golang:分析查看汇编代码查看可执行文件可视化注意:linux用户需要额外运行goinstall--tagsnowaylandloov.dev/lensm@main​下载lensm:goinstallloov.dev/lensm@main运行lensm​:lensm.\main.exe​效果:​​Gobuild​gobuild-gcflags-S.\main.go​......
  • Kaggle量化比赛复盘: Optiver - Trading at the Close
    目录前言一、开源方案1.6th获奖方案(代码未开源)1.1.特征工程(关键代码)1.2.方案解析2. 7th获奖方案(开源)2.1.特征工程2.2.特征工程3. 9th获奖方案(半开源)3.1.特征构造3.2.特征筛选3.3.模型3.4.zero_sum(标签后处理)4. 14th获奖方案(开源)4.1.方案......
  • golang学习路线
    golang学习路线学习Golang的路线可以分为以下几个阶段:基础语法:了解Golang的基本语法结构,包括变量声明、控制流、函数、指针等。数据类型:熟悉Golang的基本数据类型,如整型、浮点型、字符串、数组、切片、Map等。并发编程:学习Golang的并发编程特性,包括goroutines、channels和互斥......