GO语言学习——(3) channel之影响发送方的原值

   当接收方从通道接收到一个值类型的值时,对该值的修改就不会影响到发送方持有的那个原值。但对于引用类型的值来说,这种修改会同时影响手法双方持有的值。

// 86_chan传引用类型
package main

import (
	"fmt"
	"time"
)

var mapChan = make(chan map[string]int, 1)

func main() {
	synChan := make(chan struct{}, 2)
	go func() { // 用于演示接收操作
		for {
			if elem, ok := <-mapChan; ok {
				elem["count"]++
			} else {
				break
			}
		}
		fmt.Println("Stopped. [receiver]")
		synChan <- struct{}{}
	}()

	go func() { // 用于演示发送操作
		countMap := make(map[string]int)
		for i := 0; i < 5; i++ {
			mapChan <- countMap
			time.Sleep(time.Millisecond)
			fmt.Printf("The count map: %v. [sender]\n", countMap)
		}
		close(mapChan)
		synChan <- struct{}{}
	}()
	<-synChan
	<-synChan
	fmt.Println("#####END####")
}

运行结果:

The count map: map[count:1]. [sender]
The count map: map[count:2]. [sender]
The count map: map[count:3]. [sender]
The count map: map[count:4]. [sender]
The count map: map[count:5]. [sender]
Stopped. [receiver]
#####END####

   如上述代码所示,mapChan的元素类型属于引用类型。因此,接收方对元素值的副本修改会影响到发送方持有的源值。

   不过有时候被传递的值的类型不能简单的判定为值类型或引用类型。例如,一个结构体类型的值中包含了类型为切片的字段,在这种情况下,就要特别注意,要仔细检查对他们的修改的影响,以及这种影响是否符合预期。看下面程序:

// 87_chan值传递和引用传递
package main

import (
	"fmt"
	"time"
)

//Count代表计数器的类型
type Counter struct {
	count int
}

//var mapChan = make(chan map[string]Counter, 1)

var mapChan = make(chan map[string]Counter, 1)

func main() {
	synChan := make(chan struct{}, 2)
	go func() { // 用于演示接收操作
		for {
			if elem, ok := <-mapChan; ok {
				counter := elem["count"]
				counter.count++
			} else {
				break
			}
		}
		fmt.Println("Stopped. [receiver]")
		synChan <- struct{}{}
	}()
	go func() { // 用于演示发送操作
		countMap := map[string]Counter{
			"count": Counter{},
		}
		//countMap := map[string]*Counter{
		//	"count": &Counter{},
		//}
		for i := 0; i < 5; i++ {

			mapChan <- countMap
			time.Sleep(time.Millisecond)
			fmt.Printf("The count map: . [sender]\n", countMap["count"])
		}
		close(mapChan) //无论怎样都不应该在接收端关闭通道
		synChan <- struct{}{}
	}()
	<-synChan
	<-synChan
	fmt.Println("########END#######")
}

运行结果:

The count map: . [sender]
%!(EXTRA main.Counter={0})The count map: . [sender]
%!(EXTRA main.Counter={0})The count map: . [sender]
%!(EXTRA main.Counter={0})The count map: . [sender]
%!(EXTRA main.Counter={0})The count map: . [sender]
%!(EXTRA main.Counter={0})Stopped. [receiver]
########END#######

Process finished with exit code 0

  但要是稍微修改下程序,

// 87_chan值传递和引用传递
package main

import (
	"fmt"
	"time"
)

//Count代表计数器的类型
type Counter struct {
	count int
}

//var mapChan = make(chan map[string]Counter, 1)

var mapChan = make(chan map[string]*Counter, 1)

func main() {
	synChan := make(chan struct{}, 2)
	go func() { // 用于演示接收操作
		for {
			if elem, ok := <-mapChan; ok {
				counter := elem["count"]
				counter.count++
			} else {
				break
			}
		}
		fmt.Println("Stopped. [receiver]")
		synChan <- struct{}{}
	}()
	go func() { // 用于演示发送操作
		//countMap := map[string]Counter{
		//	"count": Counter{},
		//}
		countMap := map[string]*Counter{
			"count": &Counter{},
		}
		for i := 0; i < 5; i++ {

			mapChan <- countMap
			time.Sleep(time.Millisecond)
			fmt.Printf("The count map: . [sender]\n", countMap["count"])
		}
		close(mapChan) //无论怎样都不应该在接收端关闭通道
		synChan <- struct{}{}
	}()
	<-synChan
	<-synChan
	fmt.Println("########END#######")
}

运行结果会不一样,自己运行下看看,注意遇上一个程序的区别:*和&

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值