Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Google Go语言中,哪些类型是可变的和不可变的?_Go_Immutability_Mutability - Fatal编程技术网

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

在Google Go语言中,哪些类型是可变的和不可变的?,go,immutability,mutability,Go,Immutability,Mutability,在GoogleGo中,我读到字符串是不可变的,但int是吗? 其他类型的呢?作为一个稍老一点的程序员,我更喜欢易变性,尽管我知道不变性的好处,但我更喜欢危险地生活 了解哪些类型是可变的或不可变的将非常有用 更新,我最关心的是实际问题,这取决于类型是可变的还是不可变的。与Java中的典型示例一样,如果在循环中创建一个字符串并循环10000次,将创建10000个字符串,这些字符串随后将被垃圾收集。在我工作的一家公司的一个项目中,这实际上是一个严重的问题 问题是,Go的不变性在某些情况下会导致同样的

在GoogleGo中,我读到字符串是不可变的,但int是吗? 其他类型的呢?作为一个稍老一点的程序员,我更喜欢易变性,尽管我知道不变性的好处,但我更喜欢危险地生活

了解哪些类型是可变的或不可变的将非常有用


更新,我最关心的是实际问题,这取决于类型是可变的还是不可变的。与Java中的典型示例一样,如果在循环中创建一个字符串并循环10000次,将创建10000个字符串,这些字符串随后将被垃圾收集。在我工作的一家公司的一个项目中,这实际上是一个严重的问题

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

它会影响你应该如何对待风险值(或者我认为是这样)


再次更新,我还关注其他实际问题。知道某些东西是不可变的意味着我可以编写并行的代码,并且对对象的一个引用的更新不应该更新其他引用。然而,有时我希望做危险的事情,我希望可变

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

是的,不可变性这个词在Go规范中只出现过一次。这是在讨论
类型字符串时出现的。我认为你应该从和的双重角度来看待它。例如,Go显然会禁止您将变量重新绑定到具有未报告属性的类型的不同值。有点像C++中不提供拷贝构造函数的类,但是在GO中感觉不太尴尬,适合GrutuTin的<强>共享,

>“可变形性”只有当你谈到一些复合类型时,才有意义,有些东西有“内部”部分,这也许可以独立于包含它的东西而改变。字符串自然是由字符组成的,语言中没有任何机制允许我们更改现有字符串中的字符,除非指定一个全新的字符串,所以我们说它是不可变的

对于int,谈论易变性是没有意义的,因为int的“组件”是什么?您可以通过分配一个全新的整数来更改一个整数,但该分配不算作“变异”

易变性和引用与值类型之间存在某种联系。从语义上讲,不可变引用类型和值类型之间没有区别。为什么?假设int实际上是指向不可变对象的指针(即,
*InternalIntObject
,没有用于更改
InternalIntObject
的函数)。一旦将这样的指针指定给变量,它将永远表示相同的整数值(共享同一对象的其他人无法更改),因为该对象是不可变的。这与整数值类型的行为相同。您可以通过赋值运算符指定整数;同样,您可以通过赋值来赋值这些指针;结果将是相同的:分配的变量表示与分配给它的相同的整数。唯一的区别是比较,必须重新定义算术运算符以取消引用指针以计算结果

因此,可变性仅对引用类型有意义


至于你所问的,“可变”类型通常被认为是除了字符串之外的引用类型:映射、通道、切片(关于切片所指向的数据),以及指向任何东西的指针(因为你可以在指针指向的位置上改变值)。

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

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

  • 类型为
    int

然后答案是:整型变量是可变的,整型值是不可变的。

该视图与Go规范一致,Go规范规定字符串是不可变的。显然,字符串变量是可变的

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

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

可变Go对象:

  • 阵列和切片
  • 地图
  • 渠道
  • 从外部范围捕获至少1个变量的闭包
不可变Go对象:

  • 接口
  • 布尔值、数值(包括
    int
    类型的值)
  • 指针
  • 函数指针和可简化为函数指针的闭包
  • 具有单个字段的结构
<>去一些人可能认为易变的对象,而其他人可能认为它们是不可变的:

  • 具有多个字段的结构
    • 别担心——如果你真的想,Go会让你射中自己的脚:-)

      Go不像Erlang,这可能就是你在这个问题上的用意

      x := 1
      x = 2
      
      分配一个值为
      1
      的变量
      x
      ,然后将其重新分配给
      2
      ——此处不分配额外内存

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

      Russ Cox关于这一点的帖子应该可以回答您关于基本数据结构的大部分问题:

      正如其他评论者所指出的,您需要了解Go函数的值语义——它们一开始可能有点令人惊讶

      如果您具有以下功能:

      func (t MyType) myFunc() {
          // do something to set a field in t
      }
      
      然后你调用你的代码

      myVar.myFunc()
      
      您可能会惊讶地发现,这并不能满足您的需求,因为我使用的
      t
      func (t *myType) myFunc() {
          // do something to set a field in t
      }