Google Go语言中哪些类型是可变的和不可变的?

Phi*_*hil 31 immutability go mutability

在Google Go中,我读到字符串是不可变的,好吧但是是int?其他类型呢?作为一个稍微老一点的程序员,我更喜欢可变性,即使我知道不变性的好处,我更喜欢生活危险.

知道哪些类型是可变的或不可变的将是非常有帮助的.


更新,我最关心的是实际问题取决于类型是可变的还是不可变的.与Java中的典型示例一样,如果在循环中创建一个String并循环10,000次,则将创建10,000个String,然后进行垃圾回收.在我工作的公司的项目中,这实际上是一个严重的问题.

问题是,Go的不变性在某些情况下会导致同样的问题吗?

它会影响你应该如何对待var.(或者我认为它确实如此).


再次更新,我也关注其他实际问题.知道某些东西是不可变的意味着我可以编写并行的代码,并且对该对象的一个​​引用的更新不应该更新其他引用.但有时候我想做危险的事情,我想要变性.

这些是可变性与不变性的结果,并影响我如何编写代码.

小智 32

别担心 - 如果你真的想,Go会让你自己在脚下射击:-)

Go不像Erlang,这可能是你对问题的看法.

x := 1
x = 2
Run Code Online (Sandbox Code Playgroud)

分配一个变量,x值为1,然后重新分配给2- 这里没有分配额外的内存.

正如您所注意到的,字符串是不可变的,因此执行字符串操作可能会导致复制.如果你发现你想要做的就地修改字符数据,你可能会想对变量进行操作[]byte通过bytes包.

Russ Cox关于此的帖子应该回答大部分关于基本数据结构的问题:http://research.swtch.com/2009/11/go-data-structures.html

正如其他评论者所指出的那样,你会想看看Go函数的值语义 - 起初它们可能有点令人惊讶.

如果您具有以下功能:

func (t MyType) myFunc() {
    // do something to set a field in t
}
Run Code Online (Sandbox Code Playgroud)

你打电话给你的代码

myVar.myFunc()
Run Code Online (Sandbox Code Playgroud)

你可能会惊讶地看到你想要的东西,因为这并不做t是在看到myFunc()确实是一个复制myVar.

但是,以下内容起作用:

func (t *myType) myFunc() {
    // do something to set a field in t
}
Run Code Online (Sandbox Code Playgroud)

因为该函数具有指针的副本,并且可以通过该指针访问底层结构.

  • 谢谢!这正是我调试方法签名中缺少星号的问题所需的信息。令我惊讶的是,在这方面,Go 会让你如此轻松地用脚射击自己,而当它以其他方式“帮助”你时如此令人讨厌的声音。 (3认同)

小智 11

在我看来,首先应该分开以下两个概念:

  • 整数作为数学对象(即:值)

  • 类型的变量 int

然后答案是:整数变量是可变的,整数值是不可变的.

此视图与Go规范一致,该规范声明字符串是不可变的.显然,字符串变量是可变的.

Go中的变量(作为一个概念)至少是:

  • 命名变量(如:var i int)
  • 可通过指针访问的变量

Mutable Go对象:

  • 数组和切片
  • 地图
  • 渠道
  • 从外部范围捕获至少1个变量的闭包

不可变的Go对象:

  • 接口
  • 布尔值,数值(包括类型的值int)
  • 字符串
  • 指针
  • 函数指针和闭包可以简化为函数指针
  • 具有单个字段的结构

去某些人可能认为可变的对象,而其他人可能认为它们是不可变的:

  • 具有多个字段的结构