Golang Go语言中 我就不用指针不行?

发布于 1周前 作者 nodeper 来自 Go语言

rt ,

搜索引擎告诉我的都是,要改变属性的话就要传指针。是因为如果用值传递,会进行复制一份。这我能理解。

如果不需要改属性就使用值传递,但是不也是复制了一份吗???只不过我没修改属性罢了。

那综上改属性和不改属性都会复制。那什么时候应该用值传递?值传递的所谓的复制一份,危害性很大?那为什么 go 要设计出值传递?

还有人说无脑用指针就行?平时的 crud 里,除了查询出结果的时候,做的赋值动作。需要指针,其他函数之间的流转基本都不会去修改属性的。我用值传递不行吗。

求大佬解答


Golang Go语言中 我就不用指针不行?

更多关于Golang Go语言中 我就不用指针不行?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

29 回复

你以前用什么语言,没有值传递、引用传递的区别吗?

更多关于Golang Go语言中 我就不用指针不行?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


指针很小,复制的代价很小很小。
值复制不依赖 gc ,可以减轻 gc 压力。只读的情况下通常复制值给程序带来的压力更小。所以通常建议读取的时候用值复制。
你说的很乱,没太看懂

深拷贝损失性能
你可以去写 JavaScript (

了解了,描述不太清楚

go 里面参数传递只有值拷贝这一种方式, 你说的"值传递"和"传指针"两者的区别仅仅在于是拷贝的是一整个结构体还是指针
无脑用指针也是不可取的, 因为内存逃逸的原因, GC 压力会很大.
一般来说在 crud 里, 查询结果返回使用指针传递, 请求的参数结构体 /中间变量直接使用结构体.

不是大块数据结构,内存复制快啊,以前写 java 好像只有 integer 这些基础类型会拆箱成值传递,其他都是对象分配在堆上传引用,go 自己怎么传自由一点。

值传递又不是 go 独有的, 很多语言都有值传递, 而且占据大多数, 像 c 和 java.
而且 java 不存在引用传递一说, 全都是值传递. 只是传递对象的时候, 传递的是对象的指针, 所以仿佛看上去像引用传递而已.
值传递的目的应该是为了减少变量的作用范围, 因为要用到引用传递的地方通常是没有值传递多的.
很多时候, 一个函数输入数据, 输出数据, 不需要改变原输入数据.

而且正如楼上说的, 值传递复制的变量是在栈上的, 出了方法就自动销毁, 回收代价很小, 分配很快.

不改属性确实直接可以用值,但是如果结构数据很大,copy 性能较低

之前一直以为 Go 的 值传递也和 Swift 一样是 Copy-on-Write … 😂

不改变属性应该用

const T&

或者 非 mut borrowing

手动狗头.jpg

粗暴点来讲:
对象生命周期很长的,用指针来传
对象结构数据很大的,用指针来传

其他不改动属性的情况,无脑用值

所有语言传参都是传值!!!!!!但值的意义由你来定。

go 的指针是安全的,不想 C 的

赞同你的意见; 大多数时候无脑用值, 还能避免很多空指针的 panic

非超级大数据量值传递没有危害,甚至都不会影响电脑性能。

内存拷贝的压力很小的,试了下,采集 4 台射频信号,100M IQ 采样速率(每台每秒 100 * 2 * 2 = 400Mbyte )改用内存拷贝的方式再进行数据运算处理抽值绘制波形图,也够的,不影响电脑使用。当然,还是会选择用指针的方式来操作数据。

#13 啊?!!!!!! 你是怎么敢打那么多感叹号的

!!!!!!!!!!!!!!!!!

如下机制必须使用指针:

type T struct {
Field int
}

func (t *T) SetValue(v int) {
t.Field = v
}

var t T
t.SetValue(1) // 否则 t 的值永远不会改变

如下结构传递值会有问题:
defer func(v T){someChan <-v}(vv) // channel 捕捉不到 v 的最后状态而是当前值

gorm 的 scan 使用了大一 C 语言教科书级别的指针传递:
db.Where(“id = ?”, 1).Scan(&ModeledValue)




无脑用指针的话:

func (*T) TableName() string {
return “t_”
}

你要写 db.Table((&T{}).TableName()) ,本来可以 db.Table(T{}.TableName())




还有浅拷贝的问题:

type T struct{v:int}
type U struct{t *T}
type N struct {u *U}

t := T{v:1}
u := U{}
n := N{}

n.u = &u
u.t = &t


func foo(n *N) N {
return N{u: &U{t: n.u.t}}// 我想「用 n 的值初始化一个新 N 」
}

newN := foo(&n)
newN.u.t.v = 2
n.u.t.v == 2 //但其实 n.u.t 被改了


ref: https://go.dev/play/p/74Q6bC13xN0

排除需要修改值得情况,大部分人纠结传指针还是传值往往是在纠结对 struct 来说,我到底是该传值还是指针

很多人都会有种误解,认为传 struct 的指针比复制一份值快很多,所以喜欢传 struct 的指针。但实际上并不是的,指针引用的对象是分配到堆上的,在函数内使用指针引用的值都需要取堆去取,并且堆中的内存受 GC 管理会增加 GC 压力。而传值的话复制后的值会直接分配在栈上,栈的速度比堆快,并且函数执行完毕后栈会销毁没有 GC 之类的压力。

所以传值还是传指针,还是要取决于 struct 的大小,如果 struct 本身很大,复制一个 struct 的成本大于用指针直接引用的性能消耗那么可以考虑传指针。

优先使用值传递。如果指针传递更优,go 就不会默认用值传递了。两篇文章参考:

值传递 vs 指针传递 https://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/
值返回 vs 指针返回 https://philpearl.github.io/post/bad_go_pointer_returns/

因为 go 没有 rust 的不可变借用

语言设计成值语义还是对象语义只是一种品味问题。
可以看看陈硕的文章: https://www.cnblogs.com/solstice/archive/2011/08/16/2141515.html

在默认对象语义的语言里,比如 Python 这种,想要复制一份值要显式的调用 copy.deepcopy(),否则可能在函数里意外地修改函数外变量的值,很容易创造隐藏的 bug 。

大一第一学期 C++课就说了啥时候传参用指针和引用,一是改变值,二是数据太大复制浪费时间和空间,依稀记得这个大一的期末考也会考。

这是 stackoverflow 大学毕业的吗?

什么叫 go 设计出值传递, 所有的数据都是值, 包括指针也是 4 字节或者 8 字节的值, OK?

可以,就是对其他程序员不好理解。
性能没差多少,倒是很好通过 channel 扩展。

我都是传递结构体的时候用引用,单变量不需要修改的直接传, 切片和 map 本身就有引用树形所以也直传

在Golang(通常简称为Go)中,指针并不是强制使用的,但在某些情况下,使用指针可以带来性能上的优势或代码上的便利性。以下是一些使用指针的常见场景和原因:

  1. 性能优化:当你需要传递大型结构体或数组时,使用指针可以避免拷贝,从而提高性能。直接传递结构体的引用(即指针)比传递整个结构体更加高效。

  2. 函数修改参数:在Go中,函数的参数是按值传递的。如果你想让函数能够修改传入变量的值,那么必须传递该变量的指针。这样,函数内部对指针指向的值进行修改,会影响到外部变量。

  3. 实现接口和多态:在某些情况下,使用指针来实现接口可以使得代码更加灵活,因为接口的实现者可以动态地改变指针指向的对象。

  4. 节省内存:对于频繁分配和释放的小对象,使用指针可以减少内存的使用,因为指针本身的大小是固定的(通常是4或8字节),而对象的实际内容可以按需分配。

然而,对于简单的数据类型(如基本数据类型int、float64等)或不需要修改的函数参数,直接传递值而不是指针通常是更好的选择,因为这样可以避免额外的指针解引用操作,并且代码更加直观易懂。

总之,在Go中是否使用指针取决于具体的需求和场景。在大多数情况下,你可以根据代码的可读性和性能要求来做出选择。

回到顶部