2 回答
TA贡献1799条经验 获得超9个赞
vAge
不被视为仅是“值变量”,因为它是内存中存储type值的已知位置age
。纵观vAge
只能作为它的价值,vAge.Set(10)
是不是因为对自己的表现有效的,但由于vAge
是可寻址的,该规范宣称它的好来治疗表达简写为“获得vAge的地址,并调用设置该”编译-time时,我们将能够验证这Set
是为age
或方法设置的一部分*age
。您基本上允许编译器在确定必要和可能的情况下对原始表达式进行文本扩展。
同时,编译器将允许您调用,age(23).String()
但不允许age(23).Set(10)
。在这种情况下,我们正在使用type的不可寻址值age
。由于说的无效&age(23)
,所以说的无效(&age(23)).Set(10)
; 编译器不会进行该扩展。
查看Effective Go示例,您并没有直接调用b.Write()
我们知道b
的完整类型的范围。相反,您是制作的临时副本,b
并尝试将其作为type的值传递出去interface io.Writer()
。问题在于,实现Printf
不会对传入的对象一无所知,只是它承诺会知道如何接收Write()
,因此它不知道在调用函数之前将abyteSlice
转换为a即可*ByteSlice
。是否寻址的决定b
必须在编译时进行,PrintF
其前提是其第一个参数知道如何在Write()
不被引用的情况下进行接收。
您可能会认为,如果系统知道如何获取age
指针并将其转换为age
值,那么它应该可以执行相反的操作;但是,实际上并没有意义。在Effective Go示例中,如果要传递b
而不是&b
,则将修改一个在PrintF返回后将不再存在的切片,这几乎没有用。在age
上面的示例中,采用值23
并用value覆盖它实际上没有任何意义10
。在第一种情况下,让编译器停止并询问程序员在移交时真正意味着什么是有意义的b
。在后一种情况下,对于编译器而言,拒绝修改常量值当然是有意义的。
此外,我不认为系统正在动态地将age
的方法设置扩展为*age
;。我的疯狂猜测是,为每种基本类型的方法静态地赋予了指针类型一个方法,该方法只是取消引用指针并调用该基本方法。自动执行此操作很安全,因为按值接收方法中的任何内容都无法更改指针。在另一个方向上,通过包装被要求修改数据的方法来扩展一组要求修改数据的方法并不总是很有意义,因为它们所修改的数据此后不久就会消失。在某些情况下,这样做确实是有意义的,但是这需要程序员明确地决定,并且编译器停止并要求这样做是有意义的。
tl; dr我认为,Effective Go中的段落可能需要重新措辞(尽管我可能太long了以至于无法胜任),但这是正确的。类型的指针*X
实际上可以访问的所有X
方法,但“ X”不能访问*X
的。因此,当确定一个对象是否可以满足给定的接口时,*X
被允许满足X
可以实现的任何接口,但是反之则不成立。此外,即使X
已知作用域中的类型变量在编译时是可寻址的,所以编译器可以将其转换为*X
-它会出于接口实现的目的而拒绝这样做,因为这样做可能没有意义。 。
- 2 回答
- 0 关注
- 226 浏览
添加回答
举报