3 回答

TA貢獻1900條經(jīng)驗 獲得超5個贊
您所遇到的通常稱為“可變陰影”。當(dāng)您:=在內(nèi)部范圍內(nèi)使用任何變量時,包括在語句中if,for盡管沒有大括號,但新值和類型與該變量相關(guān)聯(lián):
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"
有幾種不同的方法可以解決此問題:
在使用它們之前聲明您需要的變量并使用普通賦值
=
使用不同的變量名
創(chuàng)建一個新范圍并保存變量的值以供以后訪問,根據(jù)需要使用變量名稱
:=
,并在范圍結(jié)束之前恢復(fù)該值;使用不同的變量名通常更容易,因為無論如何您都在創(chuàng)建另一個變量
也可能發(fā)生相反的效果,您在內(nèi)部范圍內(nèi)聲明某些內(nèi)容但沒有意識到:
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)
}
在使用它們之前聲明您需要的變量并使用普通賦值
=
將第一個
:=
和if
語句分開,因此變量按預(yù)期聲明;這允許您=
在該范圍的上下文以及包含它的任何范圍內(nèi)使用該變量的所有其他實例更改
=
to 的所有實例:=
以修復(fù)錯誤
請注意,當(dāng)函數(shù)返回多個值時,您可能會在最后兩種情況下遇到變量陰影問題,但這可以按照上面的說明解決。
在 Go Playground 上嘗試這兩個示例。
您的最后一個示例說明了聲明和初始化新變量b同時還為現(xiàn)有變量賦值的組合a。沒有創(chuàng)建新范圍,因此您不會隱藏原始變量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`
當(dāng)然,如果你沒有聲明b,那么你會從編譯器收到一個錯誤,即:=第二個聲明的左側(cè)沒有新變量,這是一種迂回的說法,你正在嘗試聲明a在同一范圍內(nèi)兩次。
請注意,如果仔細應(yīng)用此想法,也可用于查找被遮蔽的變量。例如,您的示例中的“不工作”代碼將打印不同的地址a,具體取決于a內(nèi)部范圍內(nèi)部是否已聲明:
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`

TA貢獻1847條經(jīng)驗 獲得超11個贊
根據(jù) golang 的文檔:
在塊中聲明的標(biāo)識符可以在內(nèi)部塊中重新聲明。
這正是您的示例所顯示的內(nèi)容,由于“:=”,因此在括號內(nèi)重新聲明了 a,并且從未使用過。
一個解決方案是聲明兩個變量然后使用它:
var a, b int
{
b, a = 2, 3
fmt.Println(b)
}
fmt.Println(a)

TA貢獻2016條經(jīng)驗 獲得超9個贊
您的問題有兩部分:
第一部分:
= 只是分配
:= 是為功能塊(非全局)內(nèi)的新變量(至少一個新變量)定義和分配,工作示例:
package main
import (
"fmt"
)
func main() {
var u1 uint32 //declare a variable and init with 0
u1 = 32 //assign its value
var u2 uint32 = 32 //declare a variable and assign its value at once
//declare a new variable with defining data type:
u3 := uint32(32) //inside the function block this is equal to: var u3 uint32 = 32
fmt.Println(u1, u2, u3) //32 32 32
//u3 := 20//err: no new variables on left side of :=
u3 = 20
fmt.Println(u1, u2, u3) //32 32 20
u3, str4 := 100, "str" // at least one new var
fmt.Println(u1, u2, u3, str4) //32 32 100 str
}
第二部分:
在塊中聲明的標(biāo)識符可以在內(nèi)部塊中重新聲明。
這里有 4 個不同的可變范圍和陰影工作示例:
限制變量范圍的簡單方法:
package main
import "fmt"
func main() {
i := 1
j := 2
//new scope :
{
i := "hi" //new local var
j++
fmt.Println(i, j) //hi 3
}
fmt.Println(i, j) //1 3
}
使用函數(shù)調(diào)用限制變量范圍:
package main
import "fmt"
func fun(i int, j *int) {
i++ //+nice: use as local var without side effect
*j++ //+nice: intentionally use as global var
fmt.Println(i, *j) //11 21
}
func main() {
i := 10 //scope: main
j := 20
fun(i, &j)
fmt.Println(i, j) //10 21
}
在語句中使用簡寫賦值:
package main
import "fmt"
func main() {
i := 10 //scope: main
j := 4
for i := 'a'; i < 'b'; i++ {
fmt.Println(i, j) //97 4
}
fmt.Println(i, j) //10 4
if i := "test"; len(i) == j {
fmt.Println(i, j) // i= test , j= 4
} else {
fmt.Println(i, j) //test 40
}
fmt.Println(i, j) //10 4
}
陰影全局變量:
package main
import "fmt"
var i int = 1 //global
func main() {
j := 2
fmt.Println(i, j) //1 2
i := 10 //Shadowing global var
fmt.Println(i, j) //10 2
fun(i, j) //10 2
}
func fun(i, j int) {
//i := 100 //no new variables on left side of :=
fmt.Println(i, j) //10 2
}
- 3 回答
- 0 關(guān)注
- 189 瀏覽
添加回答
舉報