当前位置: 首页 > 面试题库 >

Golang混合分配和声明

微生毅
2023-03-14
问题内容

我开始与go一起工作了几个星期,(再一次)我偶然发现了一些对我来说似乎很奇怪的东西:

// Not working
a := 1
{
    a, b := 2, 3
}

// Works
a := 1
a, b := 2, 3

play

我想同时分配两个变量。一个已经被声明,在更好的范围内,另一个没有被声明。

它不起作用:编译器尝试重新声明前一个变量。但是,如果在同一范围内声明此变量,则效果很好。

这是为什么?


问题答案:

您所经历的通常称为 “可变阴影”
。当您使用:=在内部范围内的任何变量,包括像语句iffor尽管缺乏支撑的,一个新的类型和值与该变量关联:

n := "Example"
//Prints the string variable `n` to standard output and
// returns the number of bytes written in int variable `n` and
// an error indicator in error variable `err`.
if n, err := fmt.Println(n); err != nil {
    panic(err)
} else {
    fmt.Println(n, "bytes written")
}

//Prints the string variable `n` to standard output.
fmt.Printf("n = %q\n", n)

输出:

Example
8 bytes written
n = "Example"

有几种解决此问题的方法:

  • 在使用变量之前声明您需要的变量,并使用常规赋值 =
  • 使用不同的变量名
  • 创建一个新的作用域并保存变量的值以供以后访问,根据需要使用变量名:=,并在作用域结束之前恢复该值;通常,仅使用不同的变量名会更容易,因为无论如何您都在创建另一个变量

当您在内部范围中声明某些内容却没有意识到时,也会发生相反的效果:

if _, err := fmt.Println(n); err != nil {
    panic(err)
} else {
    fmt.Println(n, "bytes written")
}

//undefined: err
if _, err = fmt.Println(n); err != nil {
    //undefined: err
    panic(err)
}

同样,有几种不同的方法可以解决此问题:

  • 在使用变量之前声明您需要的变量,并使用常规赋值 =
  • 将first :=ifstatement 分开,以便按预期声明变量;这使您可以=在该范围以及包含该范围的任何范围的上下文中使用该变量的所有其他实例
  • 改变的所有实例=,以:=修正错误

请注意,当函数返回多个值时,在后两种情况中的任何一种情况下,您都可能会遇到变量阴影问题,但是可以如上所述解决。

在Go Playground上尝试两个示例。

最后一个示例说明了声明和初始化新变量,b同时还为现有变量分配值的组合a。没有创建新的作用域,因此您不会隐藏原始变量a,可以通过a在每次赋值之后(但在下一个声明/赋值之前)打印的地址来进行验证:

a := 1
fmt.Println(&a)
a, b := 2, 3
fmt.Println(&a)
a = b          // avoids a "declared but not used" error for `b`

当然,如果您没有声明b,那么您将收到编译器的错误消息,即:=第二个声明的左侧没有新变量,这是您尝试声明的一种a回方式。a在同一范围内两次。

请注意,如果仔细应用此想法,也可用于查找阴影变量。例如,您的示例中的“不起作用”代码将为打印不同的地址a,具体取决于a内部作用域是否已声明:

a := 1
{
    fmt.Println(&a)    // original `a`
    a, b := 2, 3
    fmt.Println(&a)    // new `a`
    a = b              // avoids a "declared but not used" error for `b`
}
fmt.Println(&a)        // original `a`


 类似资料:
  • 我试图在声明性和命令式配置的混合中设置(J)缓存,因为JCache标准没有提供限制缓存可以占用的最大大小的方法。我想尽可能地“独立于提供者”,这样我将来就可以灵活地更改提供者。目前我有使用Java7的限制,所以我相信咖啡因被丢弃了。 我在应用程序中保留了缓存列表和它们条目的持续时间(TTL)。yaml,这是我用属性加载器得到的。然后,我用以下代码创建缓存: 无论我在POM中使用哪个JCache提供

  • 问题内容: 我目前正在做一个包含多重匹配和功能得分的查询。JSON的重要部分如下所示: 但是,我也想包括不一定与查询匹配但具有大于0的特定数值的结果。我认为布尔查询可以做到这一点,但是我不知道如何将布尔查询与功能分数查询。 我知道多重匹配查询只是布尔查询的简写,我可以将多重匹配查询扩展到其布尔匹配部分,但是,我不知道如何在其中进行功能评分。 有任何想法吗?顺便说一下,我的版本是1.1.0。 问题答

  • 问题内容: 我正在构建一个新的应用程序,该应用程序通过java配置而不是xml配置spring。此应用程序依赖于使用xml样式配置的模块。当我尝试启动我的应用程序时,出现以下错误: 该bean应该在模块的applicationContext.xml中声明。处理此问题的正确方法是什么?我尝试简单地添加它,就像我在应用程序的web.xml中将应用程序上下文串联在一起时一样: 但是我仍然遇到同样的错误。

  • 问题内容: 是否有人将Hamcrest与TestNG集成在一起,以便其匹配器可以轻松地用于TestNG断言中? 问题答案: 简而言之,要回答您的问题:您不需要将TestNG与Hamcrest集成。只需直接调用哪个抛出。 背景 我通过Google找到了您的问题,想知道完全一样的问题。在进一步谷歌搜索之后,我没有找到满意的答案,因此我阅读了JUnit与Hamcrest集成的源代码。 对于JUnit,通

  • 问题内容: 我一直在用Python开发一个库,我想做一些性能改进。 是否可以在Python中编写一些代码并在Go中编写一些代码,并在它们之间传递数据?如果可能的话,是否有任何有关此操作的示例? 像这样: 问题答案: 你需要一个 胶 之间,例如编程语言或通信通过网络。如果您将https://docs.python.org/2/extending/extending.html与http://golan

  • 我扩展了FlowJob类,并将其设置为: 如你所见,我想做的如下: 执行步骤1 当我运行作业时,步骤1和2正确执行,然后作业终止。 知道吗? 编辑:SO Spring批处理流程/步骤后拆分的相关问题。