I started working with go for a few weeks, and (once again) I stumbled across something that seems odd for me:
// Not working
a := 1
{
a, b := 2, 3
}
//
your Question has 2 parts:
first part:
= is just assignment
:= is define and assign for new vars(at least one new var) inside the function block(not global), working sample:
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
}
second part:
An identifier declared in a block may be redeclared in an inner block.
Here 4 different working samples for Variable scoping and shadowing:
simple way to limit variables scope:
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
}
limit variable scope using function calls:
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
}
using short-hand assignment inside statements:
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
}
shadowing global vars:
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
}