【问题标题】:Constant Parameter in golang functiongolang函数中的常量参数
【发布时间】:2014-02-28 09:40:03
【问题描述】:

我是 golang 的新手。是否可以在函数中将参数标记为常量? 以免参数被误修改。

【问题讨论】:

  • 没有常量参数并不会阻止我们想要实现的目标,但我觉得它的存在提供了该功能的明确意图。例如 c 中的 strlen(const char *str) 表示它不会修改输入字符串。
  • Chisnall in Go Programming Language Phrasebook 建议在 Go 中始终按值传递,除非您明确需要修改参数:编译器足够聪明,知道该做什么。发明 Go 的原因之一是程序员不必担心这些细节。当我第一次开始玩 Go 时,我还尝试将 C++ 和 Delphi 类比 - 现在我不再这样做了(这里的“GoTo”家伙对此非常有帮助)
  • 出于内存优化的原因,go FAQ 还建议使用引用来传递大结构,即使它们没有被修改。当 const 参数派上用场时,实际上就是这种情况。

标签: parameters go constants


【解决方案1】:

不,目前这是不可能的。有几种情况需要区分:

  • “通常”传递参数时,即按值传递参数时,您不必担心修改它,因为这些参数的行为类似于局部变量,因此您可以在函数内部修改它们,但您的更改不会在函数外可见。但是,这条规则有一个例外......
  • ...一些 Go 类型(例如指针、切片、通道、映射)是引用类型,这意味着对它们的更改在函数之外可见。一些细节已经给出here
  • 您可以将指针(例如,结构)作为参数传递,在这种情况下,更改将在函数外部可见。如果这不是故意的,那么目前您无能为力。因此,如果您要传递指针以避免复制大型结构,最好谨慎使用 - 请记住,“过早的优化是万恶之源”。 Go FAQ here 中给出了一些提示(它指的是方法接收器,但也适用于参数)。

【讨论】:

  • 是的,我担心参数更改会传播到函数之外。
  • @KarthikGR 你能简单地按值传递而不是传递指针吗?例如,func myFunc(arg int) 而不是 func myFunc(arg *int)
  • @weberc2 对于结构类型,我们通常通过引用来传递,这样函数栈就不会很大。
  • @KarthikGR 通常我处理的结构都很小,所以我通常不太担心堆栈大小。也许这对我来说是不好的做法,但我从未经历过堆栈溢出(当然,我的经验并不是确定的)。除了溢出堆栈,为什么要关心堆栈大小?它会比分配到堆更严重地降低性能吗?
  • @KarthikGR - 好的,所以您将指向结构的指针作为参数传递?也许你应该在你的问题中提到这一点:) 我假设你是按值传递参数。
【解决方案2】:

没有。

你可以在函数体内声明一个常量,但不能作为参数。

在 Go 中,常量是在编译时创建的,永远不会改变,而函数参数必须在运行时随着每次调用而改变。

【讨论】:

    【解决方案3】:

    按值传递的 const 参数还有一个方便的应用:不能无意中更改初始值。

    考虑以下代码:

    func Generate(count int) (value []byte) {
       value = make([]byte, count)
       for i:=0; i<count; count++ {
           value[i] = byte(i) // just for an example
       }
       return
    }
    

    这是一个有效的 Go 代码,在编译过程中没有警告或错误。这种错字可能很难追踪。

    【讨论】:

    • 您现在可以发表评论
    • 这不是 const 参数的示例用例。值类型是不可变的,没有理由将值设为 const。
    • 基本上,您无法通过使用花哨的语言结构来保护自己免受下一行代码中的错误。您可以删除 counter 变量增量语句,但仍然有错误:for i:=0; i&lt;count; {
    猜你喜欢
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多