Golang结构体使用指针和值的传递问题

本文将详细讨论在Go语言中使用指针和值传递结构体的问题,以及他们的不同和需要注意的问题;

在开始前你需要先掌握结构体的定义、声明以及使用方法;

我们先来看一段代码:

package main

type T struct{
	Value 		int
}

func main(){
	myT := T{Value:666}

	change(myT)

	println(myT.Value)

}
func change(t T){
	t.Value = 999
}

程序的输出是 666 ,因为这种方法传递的是值一个副本,在change() 函数中,你实际上修改的是副本的值;

修改程序,让它使用指针进行传递:

package main

type T struct{
	Value 		int
}

func main(){
	myT := T{Value:666}

	change(&myT)

	println(myT.Value)

}
func change(t *T){
	t.Value = 999
}

这段程序使用了&取地址操作符来获取结构体的地址,而change()函数期望一个T结构体的地址类型 *T,这里*T的意思是指向类型T值得指针;

程序运行输出 999;

但我们需要注意的是,实际上这里传递的依然是一个副本,只不过这个副本是一个地址,它指向原来的值;

所以,你可以修改 t.Value的值,但你无法修改 t;

package main

type T struct{
	Value 		int
}

func main(){
	myT := T{Value:666}

	change(&myT)

	println(myT.Value)

}
func change(t *T){
	t = &T{Value:999}
}

这段代码输出666;

那么,应该如何选择传递方式呢?

很明显,复制一个指针比复制一个结构的消耗要小的多;如果我们的结构非常复杂和庞大,那么复制结构会是一个很消耗性能的操作,在进行大量这样的操作时你的感觉会非常明显;

而使用指针则可避免这个问题;

当你的函数本意是改变原始数据时,那么肯定用指针转递;

当你的结构非常大时,比如包含庞大的切片、map时,也需要用指针转递;

但是如果你的结构体非常小,且不打算修改结构体内容,那么应该考虑使用值传递;

因为你不能保证程序没有bug导致误修改;且在某些多任务环境下,你需要为指针操作添加额外的锁操作,这样有些得不偿失。

原创内容,如需转载,请注明出处;

本文地址: https://www.perfcode.com/p/golang-struct-pointer.html

分类: 计算机技术
推荐阅读:
Linux终端如何输入复杂的命令 在Linux下,当你要输入的命令过于复杂,比如有许多参数,你可以先按 ctrl + x ,再按 ctrl + e 快速打开一个编辑器编辑命令。
MySQL AES_ENCRYPT()、AES_DECRYPT()函数 AES_ENCRYPT()和AES_DECRYPT()使用官方AES算法实现数据的加密和解密;其密钥默认长度为128位,默认块加密模式为ECB;
PySide6 事件的传播机制 在PySide6中,界面上的按钮(QPushButton)和QWidget部件都可以定义keyPressEvent来处理键盘按键事件。当按键事件发生时,系统会根据事件的传播机制来确定哪个部件的keyPressEvent方法将被执行。
function main is undeclared in the main package解决办法 这是一个Golang新手可能会碰到的低级错误,它表明你的main包中不包含main()函数;
使用PyInstaller将Python程序打包成EXE文件详细教程 通常我们执行python程序时,需要有Python环境,并要预先安装好需要使用的各个库,这样把程序给他人使用时不太方便;我们可以将python环境以及相应的运行库和程序源代码打包到一个单独的EXE文件中,这样分发程序就变得容易多了,从某种程度上说,还能起到保护程序源码不被泄露的作用。
Rust的第一个传统Hello World程序 本页将向你展示Rust的第一个传统程序;你将学会如何给程序添加注释、格式化打印文本信息,以及将Rust源码编译成可执行程序;