为什么我会收到“声明但未使用”的错误提示?

huangapple go评论92阅读模式
英文:

Why am I getting "declared but not used"?

问题

这是因为在循环中,你使用了 := 运算符来声明并初始化 prev_z 变量,这会创建一个新的 prev_z 变量,而不是更新外部的 prev_z 变量。因此,循环条件中的 prev_z 变量实际上没有被使用,而是在每次循环迭代时重新声明并初始化。要解决这个问题,你可以将 := 运算符改为 = 运算符,以便在循环中更新外部的 prev_z 变量。修改后的代码如下:

func Sqrt(x float64) float64 {
	z := 1.0
	var prev_z float64
	for (z - prev_z) != 0 {
		prev_z = z
		z -= (z*z - x) / (2*z)
		fmt.Println(z)
	}
	return z
}

这样修改后,你就不会再收到 "prev_z declared but not used" 的错误提示了。

英文:

I'm taking "a tour of Go" and for one of the exercises I've written this function:

func Sqrt(x float64) float64 {
	z := 1.0
	var prev_z float64
	for (z - prev_z) != 0 {
		prev_z := z
		z -= (z*z - x) / (2*z)
		fmt.Println(z)
	}
	return z
}

Why does this give me "prev_z declared but not used"?

答案1

得分: 4

因为你在for循环内部声明了一个类型为float64的变量(prev_z),然后你又使用:=短声明运算符(在第5行)初始化了一个同名同类型的新变量。

以下是正确的代码:

func Sqrt(x float64) float64 {
    z := 1.0
    var prev_z float64
    for (z - prev_z) != 0 {
        prev_z = z
        z -= (z*z - x) / (2*z)
        fmt.Println(z)
    }
    return z
}
英文:

Because you are declaring a variable (prev_z) of type float64 inside the for loop. and after that you are again initializing a new variable with the same name and type using the := short declaration operator(in line 5).

below is the correct code:

func Sqrt(x float64) float64 {
z := 1.0
var prev_z float64
for (z - prev_z) != 0 {
    prev_z = z
    z -= (z*z - x) / (2*z)
    fmt.Println(z)
}
return z

}

答案2

得分: 3

你的代码问题在于你在for循环内部使用了:=运算符重新声明了prev_z变量。这实际上创建了一个新的prev_z变量,其作用范围更窄,遮蔽了在循环外部声明的原始prev_z变量。由于这个新变量从未被使用,所以你会得到"prev_z declared but not used"的错误。你应该在循环内部使用=运算符而不是:=来将新值赋给现有的prev_z。

下面是修正后的代码:

func Sqrt(x float64) float64 {
    z := 1.0
    var prev_z float64
    for (z - prev_z) != 0 {
        prev_z = z
        z -= (z*z - x) / (2*z)
        fmt.Println(z)
    }
    return z
}
英文:

The issue in your code is that you're using the := operator to re-declare prev_z inside the for loop. This actually creates a new prev_z variable with a narrower scope that shadows the original prev_z variable declared outside of the loop. Since this new variable is never used, you get the "prev_z declared but not used" error, you should use the = operator instead of := inside the loop to assign the new value to the existing prev_z

This should work below

func Sqrt(x float64) float64 {
z := 1.0
var prev_z float64
for (z - prev_z) != 0 {
    prev_z = z
    z -= (z*z - x) / (2*z)
    fmt.Println(z)
}
return z

}

答案3

得分: 0

每当你使用 := 时,它会在运行时生成一个新的变量,并从该运算符右侧的值推断出该变量的数据类型。所以如果你写:

a:=1

那么你实际上创建了一个名为a的int类型变量。
在你的代码中,在for循环内部你写了:

prev_z := z

这导致创建了一个名为prev_z的新变量,它遮蔽了外部上下文中的prev_z,并且因此未被使用。

英文:

Whenever you use := , It generates new variable on fly and infer data type of that variable from the value that is present on Right hand side of this operator. So if you write:

a:=1

Then you're essentialy creating variable name a of type int.
In your code inside for loop you've written:

prev_z := z

Which leads to the creation of new variable with name prev_z which overshadows prev_z in outer context and hence it gets remained unused.

答案4

得分: 0

作为对其他评论者的补充,这种现象被称为变量遮蔽。在使用条件语句和返回错误作为第二个参数的函数时,无意中使用变量遮蔽是一个常见的错误,特别是在if/for块内部。

这本书《100个Go错误及其避免方法》(值得一读)中的例子说明了一个变量遮蔽的情况,导致一个始终为nil的变量:

var client *http.Client                          
if tracing {
    client, err := createClientWithTracing()     
    if err != nil {
        return err
    }
    log.Println(client)
} else {
    client, err := createDefaultClient()         
    if err != nil {
        return err
    }
    log.Println(client)
}
// 使用client变量

在这个例子中,我们首先声明了一个client变量。然后,在两个内部块中使用了短变量声明运算符(:=)将函数调用的结果赋值给内部的client变量,而不是外部的变量。结果,外部的变量始终为nil。

注意,这段代码可以编译通过,因为内部的client变量在日志调用中被使用。如果没有使用,我们将会得到编译错误,比如"client declared and not used"。

在你的情况下,只有一个变量,所以你只需要不使用短变量声明运算符:=重新赋值prev_z。但是如果有两个或更多的变量,你可以在if/for块内部使用临时变量,或者在块外声明这些变量。

英文:

Just as a complement to other commenters. The name of this phenomenon is variable shadowing. It's a common mistake to use it unintentionally, especially when you have conditionals and functions that return errors as second arguments inside if/for blocks.

This example from the book 100 Go Mistakes and How to Avoid Them (worth reading, btw) illustrates a case of variable shadowing that results in an always nil variable:

> var client *http.Client ❶
> if tracing {
> client, err := createClientWithTracing() ❷
> if err != nil {
> return err
> }
> log.Println(client)
> } else {
> client, err := createDefaultClient() ❸
> if err != nil {
> return err
> }
> log.Println(client)
> }
> // Use client
>
> In this example, we first declare a client variable. Then, we use the
> short variable declaration operator (:=) in both inner blocks to
> assign the result of the function call to the inner client
> variables—not the outer one. As a result, the outer variable is always
> nil.
>
> NOTE This code compiles because the inner client variables are used in
> the logging calls. If not, we would have compilation errors such as
> client declared and not used.

In your case it's just one variable, so you just don't reassign prev_z with the short assignment operator :=.
But in the case of two or more variables, you could use temporary variables inside the if/for block or declare the variables outside of the block.

huangapple
  • 本文由 发表于 2023年2月22日 06:12:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75526391.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定