即使所有方法都是使用值接收器定义的,也会改变结构体的切片字段

Don*_*per 1 pointers go slice

\n

6.2 使用指针接收器的方法

\n

如果命名类型 T 的所有方法都有 T 本身的接收者类型\n(不是 *T ),则复制该类型的实例是安全的;调用任何方法都必然会生成一个副本。例如,time.Duration\n值可以自由复制,包括作为函数的参数。但是,如果任何方法有指针接收器,则应避免复制 T 的实例,因为这样做可能会违反内部不变量。例如,复制 bytes.Buffer 的实例将导致原始\n和副本别名 ( \xc2\xa72.3.2 ) 相同的底层字节数组。\n后续方法调用将产生不可预测的影响。

\n

(Go 编程语言 Alan AA Donovan \xc2\xb7 Brian W. Kernighan)

\n
\n

我理解这句话的一般含义,但我想知道复制该类型的实例是安全的是否正确。

\n

如果结构体具有切片/映射字段,则所有副本都会收到自己的指向后备数组/哈希图的指针副本,因此仍然可以更改这些数据结构。

\n

尽管所有方法都可以使用值接收器定义,但我们可以破坏结构的内部状态。

\n

我明白为什么会发生这种情况,但是这种可能性是否与上面段落中所写的内容相矛盾?

\n

无论方法接收者如何,复制值都可能会产生不良后果,并且还取决于字段类型。

\n

我在这里缺少什么?

\n
package main\n\nimport "fmt"\n\ntype T struct {\n    s []string\n}\n\nfunc main() {\n    original := T{s: []string{"original"}}\n    copycat := original\n    copycat.s[0] = "copycat"\n    fmt.Println(original.s[0] == "copycat") // true\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Adr*_*ian 5

我既不是 Donovan,也不是 Kernighan,所以我不能明确地说出他们在这里试图传达的内容,但我的理解不是“使用值接收器使复制安全”,而是“使用值接收器表明复制是安全的”。您是正确的,任何指针字段或任何包含指针字段的字段(包括切片和映射)都会使复制不安全;我相信作者试图传达的是,使用值接收器的 API 向其消费者表明不存在这样的字段。