3a30fb8a07
Don't break urls. 1. New Route function which generates routes compatible with old blog. 2. Renamed posts folder to blog.
133 lines
2.3 KiB
Markdown
133 lines
2.3 KiB
Markdown
---
|
|
layout: post
|
|
title: "go: `:=` operator causes accidental shadowing"
|
|
date: 2016-01-14 21:13
|
|
comments: true
|
|
categories:
|
|
- go
|
|
---
|
|
|
|
Go provides `:=` operator to make declaring variables easier. It is a [shorthand to declare and set a value of a variable](https://golang.org/ref/spec#Short_variable_declarations). for example,
|
|
|
|
```go
|
|
var x int
|
|
x = 42
|
|
```
|
|
can be written as
|
|
|
|
```go
|
|
x := 42
|
|
```
|
|
But if not careful, this can accidently shadow variable bindings. Let's look at the fictitious piece of code.
|
|
|
|
```go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
|
|
func fictitiousFunc() (int, error) {
|
|
return 42, nil
|
|
}
|
|
|
|
func main() {
|
|
x := 10;
|
|
x, err := fictitiousFunc()
|
|
if err != nil {
|
|
fmt.Println("I'll never print")
|
|
}
|
|
fmt.Println("value of x: ", x)
|
|
}
|
|
```
|
|
This produces following output
|
|
|
|
```
|
|
value of x: 42
|
|
```
|
|
While, this following piece of code will fail to compile
|
|
|
|
```go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
func fictitiousFunc() (int, error) {
|
|
return 42, nil
|
|
}
|
|
|
|
func main() {
|
|
x := 10
|
|
// replace :=
|
|
var x int
|
|
var err error
|
|
x, err = fictitiousFunc()
|
|
if err != nil {
|
|
fmt.Println("I'll never print")
|
|
}
|
|
fmt.Println("value of x: ", x)
|
|
}
|
|
|
|
```
|
|
output:
|
|
```
|
|
prog.go:12: x redeclared in this block
|
|
previous declaration at prog.go:10
|
|
```
|
|
So we can see that the operator is somewhat intelligent, and does not redeclare the variables.
|
|
|
|
Now what if we push it down a scope? See the following code
|
|
|
|
```go
|
|
package main
|
|
|
|
import "fmt"
|
|
|
|
|
|
func fictitiousFunc() (int, error) {
|
|
return 42, nil
|
|
}
|
|
|
|
func main() {
|
|
someCondition := true
|
|
|
|
x := -1;
|
|
|
|
if someCondition {
|
|
x, err := fictitiousFunc()
|
|
|
|
if err != nil {
|
|
fmt.Println("I'll never print")
|
|
}
|
|
|
|
fmt.Println("value of x inside: ", x)
|
|
}
|
|
|
|
fmt.Println("value x outside: ", x)
|
|
|
|
}
|
|
```
|
|
|
|
This produces,
|
|
```go
|
|
value of x inside: 42
|
|
value x outside: -1
|
|
```
|
|
|
|
At line: 16, since the immediate scope (line:15-32) does not have variable `x` declared, `:=` is redeclaring the variable. a.k.a the __variable `x` gets shadowed__.
|
|
|
|
Only workaround I can think of is not to use `:=`, i.e change the code to
|
|
```go
|
|
if someCondition {
|
|
var err error
|
|
x, err = fictitiousFunc()
|
|
|
|
if err != nil {
|
|
fmt.Println("I'll never print")
|
|
}
|
|
|
|
fmt.Println("value of x inside: ", x)
|
|
}
|
|
```
|
|
|
|
If you know something better let me know.
|