GO——值方法与指针方法的区别

值方法与指针方法的区别

指针方法

特点

指针方法复制源值的指针并以指针参数的形式传入函数中,函数中对指针参数内容的修改即为源值内容的修改,所以会全部反应到源值上。
可对照 输出:1 2 4 佐证。

值方法

特点

值方法会创建新变量以复制源值内容,并将该新变量以值参数的形式传入函数中, 所以函数中值参数是源值内容的复制,与源值再无联系,所以函数内值参数内容的修改不会反应到源值上。
可对照 输出:1 3 4 佐证。

特例

值方法对引用类型1源值的修改,会在源值上反应。
可对照 输出:6 7 8 deskmate[0] addr 佐证。

原理

切片类型指向底层数组,是对底层匿名数组的引用。
调用值方法时复制了原址内容的的值参数指向的仍是与源值相同的底层数组,
若不触发底层数组的扩容,则对值参数的所有修改都会反应到源值上。
当对值参数的改动触发底层数组扩容时,值参数指向扩容后的新数组,源值指向旧数组。
只有此时值参数和源值才真正独立互不影响。

代码

源码
package main

import "fmt"

type Student struct {
	Age      int
	Name     string
	DeskMate []string
}

func (s *Student) SetAge(age int) {
	s.Age = age
	fmt.Printf("2 func SetAge:: addr: %p type: %T data: %+v \n", s, s, *s)
}

func (s Student) SetName(name string) {
	s.Name = name
	fmt.Printf("3 func SetName::  addr: %p %T data: %+v \n", &s, s, s)
}

func (s Student) ModifyDeskMate(deskMate string) {
	s.DeskMate[0] = deskMate
	fmt.Printf(
		"7 func ModifyDeskMate:: deskmate addr: %p deskmate[0] addr: %p  deskmate[0] data: %+v \n",
		&s.DeskMate, &s.DeskMate[0], s.DeskMate[0])
}

func main() {

	var s Student

	fmt.Printf("1 func main:: addr: %p type: %T data: %+v \n", &s, s, s)

	(&s).SetAge(12)   //完全等价于s.SetAge(12), 因为变量调用值方法/指针方法时, go内部会自动帮我们把变量转换为合适的类型
	s.SetName("anne") //完全等价于(&s).SetName("anne")

	fmt.Printf("4 func main:: addr: %p type: %T data: %+v \n", &s, s, s)

	fmt.Println("----------------------special case----------------------")

	s.DeskMate = []string{"barry", "charles"}

	fmt.Printf("5 func main:: addr: %p type: %T data: %+v \n", &s, s, s)
	fmt.Printf(
		"6 func main:: deskmate addr: %p deskmate[0] addr: %p  deskmate[0] data: %+v \n",
		&s.DeskMate, &s.DeskMate[0], s.DeskMate[0])

	s.ModifyDeskMate("anduin")

	fmt.Printf(
		"8 func main:: deskmate addr: %p deskmate[0] addr: %p  deskmate[0] data: %+v \n",
		&s.DeskMate, &s.DeskMate[0], s.DeskMate[0])

	fmt.Printf("9 func main:: addr: %p type: %T data: %+v \n", &s, s, s)
}

输出
1 func main:: addr: 0xc000060150 type: main.Student data: {Age:0 Name: DeskMate:[]} 
2 func SetAge:: addr: 0xc000060150 type: *main.Student data: {Age:12 Name: DeskMate:[]} 
3 func SetName::  addr: 0xc000060210 main.Student data: {Age:12 Name:anne DeskMate:[]} 
4 func main:: addr: 0xc000060150 type: main.Student data: {Age:12 Name: DeskMate:[]} 
----------------------special case----------------------
5 func main:: addr: 0xc000060150 type: main.Student data: {Age:12 Name: DeskMate:[barry charles]} 
6 func main:: deskmate addr: 0xc000060168 deskmate[0] addr: 0xc00000c080  deskmate[0] data: barry 
7 func ModifyDeskMate:: deskmate addr: 0xc000060378 deskmate[0] addr: 0xc00000c080  deskmate[0] data: anduin 
8 func main:: deskmate addr: 0xc000060168 deskmate[0] addr: 0xc00000c080  deskmate[0] data: anduin 
9 func main:: addr: 0xc000060150 type: main.Student data: {Age:12 Name: DeskMate:[anduin charles]} 

  1. 常见引用类型: slice, map, channel
    常见值类型: int, float, bool, string, array, struct ↩︎

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值