前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Go小技巧&易错点100例》第二十一篇

《Go小技巧&易错点100例》第二十一篇

原创
作者头像
盐咔咔
发布2024-08-21 22:28:52
1370
发布2024-08-21 22:28:52
举报
文章被收录于专栏:Go小技巧&易错点100例

本篇内容

① errors.Is方法与==方式进行error比较

② 带缓冲channel和无缓冲channel区别

正文

errors.Is方法与==两种方式进行error比较

在Go语言中,处理错误(error 类型)时,errors.Is 和直接使用 == 操作符进行错误比较,虽然看起来都用于比较错误,但实际上它们有着根本的不同。这主要体现在对错误值的比较方式和用途上。

1) 使用 == 操作符

直接使用 == 操作符来比较两个错误值,实际上是比较这两个错误变量的内存地址是否相同。这意味着,除非这两个错误变量引用的是同一个错误实例(即指向相同的内存地址),否则 == 将返回 false。这种比较方式对于区分不同的错误实例(即使它们包含相同的错误信息)非常严格,并且不常用于错误处理,因为它通常不是你所需要的比较方式。

2) 使用 errors.Is

errors.Is 函数用于判断一个错误是否是由特定的错误或错误的类型产生的。这意呀着,即使两个错误值不是同一个实例(即它们的内存地址不同),只要它们在类型上或者通过错误包装(wrapping)关系上是相关的,errors.Is 也能返回 true。

errors.Is 函数特别适合与错误包装(%w 格式化指令在 fmt.Errorf 中)一起使用,用于判断一个错误是否是由于某个特定的底层错误引起的。

代码示例

代码语言:go
复制
var myErr = errors.New("my err")

func TestError(t *testing.T) {
	err := fmt.Errorf("hello %w", myErr)

	fmt.Printf("myErr:%s , err:%s \n", myErr, err)

	fmt.Println("使用 == 的结果:", err == myErr)
	fmt.Println("使用 errors.Is(err, myErr) 的结果:", errors.Is(err, myErr))
	fmt.Println("使用 errors.Is(myErr, err) 的结果:", errors.Is(myErr, err))
}

输出:

代码语言:shell
复制
myErr:my err , err:hello my err 
使用 == 的结果: false
使用 errors.Is(err, myErr) 的结果: true
使用 errors.Is(myErr, err) 的结果: false

带缓冲channel和无缓冲channel区别

Go语言中的channel是用于在不同的goroutine之间进行通信的一种机制。channel可以是带缓冲的,也可以是无缓冲的,它们之间有一些关键的区别:

无缓冲channel

无缓冲的channel没有存储空间,发送操作会阻塞直到另一方准备好接收数据,接收操作也会阻塞直到有数据可以接收。

代码示例:

代码语言:go
复制
func TestNoBufferChannel(t *testing.T) {
	ch := make(chan int)

	go func() {
		ch <- 10
		fmt.Println("Send data to channel")
	}()

	time.Sleep(time.Second * 3) // 确保goroutine有足够的时间执行
	data := <-ch
	fmt.Println("Received data:", data)
}

输出:

代码语言:go
复制
Received data: 10
Send data to channel

带缓冲channel

Go语言中的channel是一种用于在不同的goroutine之间进行通信的机制。Channel可以是带缓冲的(buffered)或不带缓冲的(unbuffered),它们之间的主要区别在于数据的发送和接收方式。

带缓冲的channel有固定的存储空间,可以在channel满之前存储数据项。发送操作只会在缓冲区满时阻塞,接收操作会在缓冲区为空时阻塞。可以使用len函数查看当前缓冲区中剩余元素的数量,使用cap函数查看缓冲区的容量。

代码示例:

代码语言:go
复制
func TestHasBufferChannel(t *testing.T) {
	ch := make(chan int, 2) // 创建一个容量为2的带缓冲channel

	ch <- 10
	ch <- 20

	go func() {
		time.Sleep(time.Second * 2)
		ch <- 30 // 这条语句会阻塞,直到缓冲区有空间
	}()

	data := <-ch
	fmt.Println("Received data:", data)
	data = <-ch
	fmt.Println("Received data:", data)

	time.Sleep(time.Second * 3) // 等待足够的时间来接收最后一条数据
	data = <-ch
	fmt.Println("Received data:", data)
}

输出:

代码语言:shell
复制
Received data: 10
Received data: 20
Received data: 30

在无缓冲channel的例子中,主goroutine和发送goroutine之间的操作是同步的。而在带缓冲channel的例子中,发送goroutine可以继续发送数据,直到缓冲区满为止,而接收goroutine可以从缓冲区接收数据,而不需要等待发送操作

本篇结束~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • errors.Is方法与==两种方式进行error比较
  • 带缓冲channel和无缓冲channel区别
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档