我来自没有明确指示的语言,因此我并不真正理解他们存在的意义(没有双关语意)。
问题是我大多数时候都不知道为什么我要传递指向函数的指针。我确实理解当你传入指针时,对变量的修改到处都是值,但重点是什么?为什么不修改值并返回结果呢?
例如,Object
是一个接收http.HandlerFunc
和http.ResponseWriter
作为参数的函数。我已经读过接口实际上是指针(是吗?),但我没有得到的是,为什么?
为什么我会得到一个指向作家的指针?我没有修改它,我只是写它。而且,为什么我得到一个指向请求的指针?我正在做像*http.Request
这样的事情。
通过这些例子,我试图在这里确定的是问题的答案,"我什么时候需要传入指针?"
我现在这样做的方法是编写我的代码,尝试编译它,修复错误,说我必须通过添加一个&符号和星号来传递指针,直到错误通过。然而,我觉得这个半识不明的指针概念很快就会在某一天在背后咬我。
答案 0 :(得分:2)
您可以将指针视为指向对象内存地址的值。与大多数数据结构相比,指针很小(比如8个字节)。
很多时候你会得到一个指向对象的指针,因为传递这8个字节比创建你想传递的整个对象的副本要快得多。
对于Request对象,与仅传递可访问原始数据的指针相比,在请求(有效负载,标题和诸如此类型)下创建所有内容的副本将非常昂贵。
答案 1 :(得分:1)
顾名思义,指针是一个指向内存中某个位置的变量。
在复制对象的整个值因某种原因而不合理时使用它。这可能是因为对象太大而复制它会很慢,所以你只想传递一个小指针到对象并在内存中使用相同的对象(可能是http.Request是指针的原因),或者因为您需要修改对代码中其他位置可能已引用的对象的现有引用。您可以查看net / http here的代码以了解原因。 (事实上,对于任何Go标准库,如果您想以某种方式研究某些事情的原因或方式,那么代码是开放的。)
但这有点无关紧要,因为作为用户,你传递指针的原因是因为函数被定义为将指针作为参数。编写库的程序员决定使用指针的原因并不重要。您可以查找go文档,也可以执行您正在执行的操作,只需传递一个值,如果编译器抱怨修复它。
答案 2 :(得分:-1)
指针是一个非常简单的概念,当你只是理解它们是如何工作的时候,但在理解它之前它看起来真的很难和烦人的东西,特别是在C中。有指针算法,指针指向指针等。
无论如何,你不必使用指针,如果你的库不强迫你使用,但是传递变量,函数周围的数据结构可能会因为函数范围而将所有东西复制到另一个内存部分。
在大多数语言中,值都是通过文字传递的。这意味着当您将变量传递给函数或类时,它可能会复制它。
更多内存消耗,还需要CPU时间来复制项目。不太复杂。
另一方面,PHP等一些语言有一些自动化,比如copy on write algorithm
,当你将参数传递给它通过引用传递的函数时,它只将内存地址传递给函数,直到函数尝试写入这个变量,在那个时候它只是复制变量。
但自动化也会带来一些成本。这里真正的要点cost
Go试图尽可能快地减少自动化,更多的用户控制,但也试图安全和简单。不像C,C ++,它不会让你感到羞耻。
在你的例子中http.ResponseWriter
当你通过它的内存引用(作为指针)将它传递给any函数时,你在这个函数里面写了东西,它只是直接写入它,没有特殊的算法或者检查是否没有类型不匹配等可能有一些检查像垃圾收集器但它确实带来了优势而不是它的成本。
同样在PHP中,Java对象通过其引用传递,但语言只是隐藏了这种冗长。
我已经读过接口实际上是指针
不完全是,Interface{}
是Go中的基类型,所以每个类型都实现了接口类型,在这个观点上它只是一个类型,所以没有任何意义可以作为指针调用。
它为您提供了动力,例如:如果您从数据源中读取数据尚未构建且不一致的结构,则结构可以随时更改,例如XML或JSON源。只需使用界面!你已经知道每个类型的祖先都是接口,它只会在运行时处理基础结构/数据类型。
但您也可以使用Interface term来定义接口(如java,c#,php等)并放置实现方法。当满足这些方法的任何结构时。它自然地实现了接口。这种被称为Duck Typing的实现设计请阅读以获取更多信息https://en.wikipedia.org/wiki/Duck_typing