Go没有const限定符的基本原理是什么?

时间:2015-11-14 19:09:54

标签: go

我是C ++高级程序员。我正在做一些Go编程。我真正想念的唯一功能是const限定符。在go中,如果要修改对象,则传递其指针。如果您不想修改它,请按值传递它。但是如果结构很大,你应该通过指针传递它,这会覆盖无修改功能。更糟糕的是,你可以按值传递一个对象,但是如果它包含一个指针,你实际上可以修改它的内容,并带来可怕的竞争条件危险。某些语言类型(如地图和切片)具有此功能。这种情况发生在一种应该为并发而构建的语言中。所以避免修改的问题在Go中确实不存在,你应该通过值传递不包含指针的小对象(你必须知道对象不包含指针),如果他们不会被修改。

使用const,您可以通过const指针传递对象,而不必担心修改。类型安全就是要有一个允许速度和防止类型相关错误的合同。执行此操作的另一个功能是const限定符。

2 个答案:

答案 0 :(得分:2)

C / C ++中的const类型限定符具有多种含义。应用于变量时,表示该变量是不可变的。这是一个有用的功能,而且Go中缺少一个,但它不是你似乎在谈论的那个。

您正在谈论const可以用作函数的部分强制契约的方式。函数可以为指针参数提供const限定符,表示函数不会使用该指针更改任何值。 (当然,除非该函数使用强制转换(C ++中的const_cast)。或者,在C ++中,指针指向声明为mutable的字段。)

Go有一个非常简单的类型系统。许多语言都有一个复杂的类型系统,您可以通过编写类型来强制执行程序的正确性。在许多情况下,这意味着大量的编程涉及编写类型声明。 Go采用了不同的方法:大多数编程都涉及编写代码而不是类型。您可以通过编写正确的代码来编写正确的代码,而不是通过编写捕获写入错误代码的情况的类型。如果要捕获不正确的代码,可以编写分析器,例如go vet,以查找代码中无效的情况。对于Go来说,这些类型的分析器比C / C ++更容易编写,因为语言更简单。

这种方法有利有弊。 Go在这里做出了明确的选择:编写代码,而不是类型。对每个人来说,这不是正确的选择。

答案 1 :(得分:1)

请将其视为扩展评论。我不是任何编程语言设计师,所以不能深入了解这里的细节,但是我将作为C ++的长期开发人员和Go的短期开发人员提出我的看法。

Const对于编译器来说是一个非平凡的特性,因此必须确保它是否为用户提供了足够的优势来实现它,并且不会牺牲语法的简单性。您可能认为它只是我们正在谈论的const限定符,但是看看C ++本身,并不是那么容易 - 有很多警告。

  1. 您说const是一份合同,在任何情况下都不应该修改它。反对使用只读接口的一个论点是,您可以将其转换为原始类型并执行您想要的任何操作。你当然可以。通过使用const_cast,您可以使用C ++在合同中显示中指的方式相同。出于某种原因,它被添加到语言中,并且不确定我应该为此感到自豪,我已经使用过一两次。

  2. C ++中还有另一个修饰符,可让您放宽合约 - mutable。有人意识到const结构实际上可能需要修改一些字段,通常是保护内部变量的互斥锁。我猜你在Go中需要类似的东西,以便能够实现线程安全的结构。

  3. 简单const int x时,人们可以轻松关注。但随后指针跳了进来,人们真的得到了充实。 const int * xint * const xconst int * const x - 这些都是x的有效声明,每个声明都有不同的合同。我知道选择正确的C ++程序员并不是一门火箭科学,但是你作为高级C ++程序员的经验是否告诉你们人们广泛理解这些并且总是使用正确的?我甚至没有提到像const int * const * * * const * const x这样的东西。它让我大吃一惊。

  4. 在我转到第4点之前,我想引用以下内容:

      

    更糟糕的是,您可以按值传递对象,但如果它包含指针,   你可以实际修改其内容

    现在这是一个有趣的指责。 C ++中存在同样的问题;更糟糕 - 即使您将对象声明为const也存在,这意味着您无法使用简单的const限定符来解决问题。见下一点:

    1. 每3个和指针,表达非常合适的合同并不容易,事情有时会出乎意料。这段代码让一些人感到惊讶:

      struct S {
          int *x;
      };
      
      int main() {
          int n = 7;
          const S s = {&n}; // don't touch s, it's read only!
          *s.x = 666; // wait, what? s is const! is satan involved?
      }
      

      我确信你为什么编译上面的代码是很自然的。它是您无法修改的指针值(它指向的地址),而不是它背后的值。你必须承认周围的人会引起他们的注意。

    2. 我不知道它是否有任何意义,但我一直在使用C ++中的const。非常精准。精打细算。不确定是否曾经拯救过我的屁股,但在搬到Go后我必须承认我从未错过它。考虑到所有这些边缘情况和例外情况,我真的相信像Go这样的极简主义语言的创作者会决定跳过这个。

        

      类型安全就是要有一个允许速度和阻止的合同   类型相关的错误。

      同意。例如,在Go中,我喜欢类型之间没有隐式转换。这实际上阻止了我与类型相关的错误

        

      执行此操作的另一个功能是const限定符。

      根据我的答案 - 我不同意。如果一般const契约肯定会这样做,那么简单的const限定符是不够的。然后你需要一个mutable一个,也许是一种const_cast特征,但它仍然会让你误导保护,因为很难理解究竟是什么不变。

      希望一些语言创建者能够在我们的代码中设计一个完美的方法来定义常量,然后我们将在Go中看到它。或者转到新语言。但就个人而言,我认为C ++的方式并不是特别好。

      (替代方案是遵循函数式编程范式,它希望看到所有“变量”不可变。)

相关问题