Golang中自动“取引用”和“解引用”对原值的影响

1. 写在前面

我们知道Golang在调用方法时,会自动对实参进行“取引用”或“解引用”操作。我们在前面的博客Golang对方法接收者变量的自动“取引用”和“解引用”中也已经讨论了容易引起混淆的解/取引用和接口相关的知识,这里我们将讨论另一个问题:“自动取引用”和“自动解引用”会不会对原值产生影响。
我们知道这样一个规则:

规则1: 当传递给方法的实参是一个值类型时,原值的内容不会受到影响,因为传递进来的是原值的副本;相反,当传递给方法的实参是一个指针类型时,原值的内容将可能受到影响。

但本文讨论一个比较特殊的情况是:“自动解引用”时receive会从指针类型转变为值类型,而“自动取引用”时receiver会从值类型转变为指针类型,这是否会对规则1产生影响。

2. 实验验证

我们还是用代码来说明问题。demo1.go分别演示了四种情形:

  • 值类型的实参调用形参为值类型的方法
  • 指针类型的实参调用形参为值类型的方法(会进行“自动解引用”)
  • 值类型的实参调用形参为指针类型的方法(会进行“自动取引用”)
  • 指针类型的实参调用形参为指针类型的方法
//demo1.go
package main

import "fmt"

// user defines a user in the program.
type user struct {
	email string
}

// changeEmailByValue implements a method with a value receiver.
func (u user) changeEmailByValue(email string) {
	u.email = email
}


// changeEmailByPointer implements a method with a pointer receiver.
func (u *user) changeEmailByPointer(email string) {
	u.email = email
}

func main() {
	alice := user{"alice@163.com"} // value type
	fmt.Printf("Alice's original email:%s\n", alice.email)
	alice.changeEmailByValue("alice@gmail.com")
	fmt.Printf("ChangeEmailByValue with a value type: %s\n", alice.email)

	bob := &(user{"bob@163.com"}) // pointer type
	fmt.Printf("Bob's original email:%s\n", bob.email)
	bob.changeEmailByValue("bob@gmail.com")
	fmt.Printf("ChangeEmailByValue with a pointer type: %s\n", bob.email)

	carol := user{"carol@163.com"} // value type
	fmt.Printf("Carol's original email:%s\n", carol.email)
	carol.changeEmailByPointer("carol@gmail.com")
	fmt.Printf("ChangeEmailByPointer with a value type: %s\n", carol.email)

	dave := &(user{"dave@163.com"}) // pointer type
	fmt.Printf("Dave's original email:%s\n", dave.email)
	dave.changeEmailByPointer("dave@gmail.com")
	fmt.Printf("ChangeEmailByPointer with a pointer type: %s\n", dave.email)
}

代码运行结果如下图所示
代码运行结果

3. 小结

从运行结果可以发现,“自动解引用”和“自动取引用”都不会改变规则1,方法的调用是否会对原值产生影响完全取决于该方法的形参是值类型还是参数类型

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Golang,基本数据类型包括整型、浮点型、布尔型、字符串和字符型。引用数据类型包括数组、切片、映射、结构体和接口。 1. 整型:Golang提供了多种整型,包括int、int8、int16、int32、int64、uint、uint8、uint16、uint32和uint64等。它们分别表示有符号和无符号的整数,不同类型的整数有不同的值范围。 2. 浮点型:Golang提供了两种浮点型,即float32和float64。它们分别表示单精度和双精度浮点数,用于表示小数。 3. 布尔型:Golang的布尔型只有两个值,即true和false。用于表示逻辑值。 4. 字符串:Golang的字符串是一系列字节的集合,使用双引号或反引号括起来。字符串是不可变的,可以通过索引访问其的字符。 5. 字符型:Golang的字符类型使用单引号括起来,表示一个Unicode字符。 引用数据类型: 1. 数组:数组是一组具有相同类型的元素的集合,长度固定。可以通过索引访问数组的元素。 2. 切片:切片是对数组的抽象,它可以动态增长和缩小。切片是一个引用类型,可以通过切片操作符[:]来获子切片。 3. 映射:映射是一种无序的键值对集合,也称为字典或哈希表。可以通过键来访问对应的值。 4. 结构体:结构体是一种自定义的数据类型,可以包含多个字段,每个字段可以有不同的类型。结构体用于组织和存储相关的数据。 5. 接口:接口是一种抽象类型,定义了一组方法的集合。接口可以被其他类型实现,实现了接口的类型可以被当作该接口类型使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值