Difference between := and = operators in Go - go

What is the difference between the = and := operators, and what are the use cases for them? They both seem to be for an assignment?

In Go, := is for declaration + assignment, whereas = is for assignment only.
For example, var foo int = 10 is the same as foo := 10.

As others have explained already, := is for both declaration, assignment, and also for redeclaration; and it guesses (infers) the variable's type automatically.
For example, foo := 32 is a short-hand form of:
var foo int
foo = 32
// OR:
var foo int = 32
// OR:
var foo = 32
/ There are some rules: /
★ 1st Rule:
You can't use := outside of funcs. It's because, outside a func, a statement should start with a keyword.
// no keywords below, illegal.
illegal := 42
// `var` keyword makes this statement legal.
var legal = 42
func foo() {
alsoLegal := 42
// reason: it's in a func scope.
}
★ 2nd Rule:
You can't use them twice (in the same scope):
legal := 42
legal := 42 // <-- error
Because, := introduces "a new variable", hence using it twice does not redeclare a second variable, so it's illegal.
★ 3rd Rule:
You can use them for multi-variable declarations and assignments:
foo, bar := 42, 314
jazz, bazz := 22, 7
★ 4th Rule (Redeclaration):
You can use them twice in "multi-variable" declarations, if one of the variables is new:
foo, bar := someFunc()
foo, jazz := someFunc() // <-- jazz is new
baz, foo := someFunc() // <-- baz is new
This is legal, because, you're not declaring all the variables, you're just reassigning new values to the existing variables, and declaring new variables at the same time. This is called redeclaration.
★ 5th Rule:
You can use the short declaration to declare a variable in a newer scope even if that variable is already declared with the same name before:
var foo int = 34
func some() {
// because foo here is scoped to some func
foo := 42 // <-- legal
foo = 314 // <-- legal
}
Here, foo := 42 is legal, because, it declares foo in some() func's scope. foo = 314 is legal, because, it just assigns a new value to foo.
★ 6th Rule:
You can declare the same name in short statement blocks like: if, for, switch:
foo := 42
if foo := someFunc(); foo == 314 {
// foo is scoped to 314 here
// ...
}
// foo is still 42 here
Because, foo in if foo := ..., only belongs to that if clause and it's in a different scope.
So, as a general rule: If you want to easily declare a variable you can use :=, or, if you only want to overwrite an existing variable, you can use =.
References:
Short Variable Declaration Rules
A Visual Guide to Go Variables

Only = is the assignment operator.
:= is a part of the syntax of the short variable declaration clause.
👉 There are some rules though. See this other answer for more details.

:= is a short-hand for declaration.
a := 10
b := "gopher"
a will be declared as an int and initialized with value 10 where as b will be declared as a string and initialized with value gopher.
Their equivalents using = would be
var a = 10
var b = "gopher"
= is assignment operator. It is used the same way you would use it in any other language.
You can omit the type when you declare the variable and an initializer is present (http://tour.golang.org/#11).

The := means declare and assign while the = means to simply assign.

:= declares and assigns, = just assigns
It's useful when you don't want to fill up your code with type or struct declarations.
// Usage with =
var i int
var U, V, W float64
var k = 0
var x, y float32 = -1, -2
// Usage with :=
i, j := 0, 10
f := func() int { return 7 }
ch := make(chan int)

from the reference doc : (tour.golang.org)
Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type.
Outside a function, every construct begins with a keyword (var, func, and so on) and the := construct is not available.

In Go
:= is for declaration and assignment also
whereas = is only for the Assignment
for example:
var s string = "Omkar"
s:= "Omkar"

Related

Struct Field Multiple Assignment, reassignment, and shadowing in Go [duplicate]

This snippet works as expected play.golang.org/p/VuCl-OKMav
i := 10
next := 11
prev, i := i, next
However this nearly identical snippet gives non-name f.Bar on left side of := play.golang.org/p/J8NNWPugQG
type Foo struct {
Bar int
}
f := Foo{10}
next := 11
prev, f.Bar := f.Bar, next
What's special about the struct that stops type inference? Is this a bug?
It's an open issue.
Issue 6842: spec: Assigning to fields with short declaration notation
It's not really a type inference issue, it's just that the left-hand-side of := must be a list of identifiers, and f.Bar is not an identifier, so it can't be declared — not even with :='s slightly-more-permissive rules for what it can declare. See "Short variable declarations" in The Go Programming Language Specification.
From the spec's Short variable declarations section:
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block...with the same type, and at least one of the non-blank
variables is new.
So if you declare the variable inside another type (struct Foo in the example), it is disqualified by "provided they were originally declared earlier in the same block".
So the answer is to just set the pre-declared variable equal not using the := syntax to the value:
...
var prev int
prev, f.Bar = f.Bar, next
...
it is just that you already assigned f to Foo
f := Foo{100}
in this case f.Bar is 100
so to reassign it just remove the column
var prev string
f := Foo{10}
next := 11
prev, f.Bar = f.Bar, next
this will work

Question about Map, String Pointers and Closure

I discovered a bug with my code when I was trying to convert map[string]string to map[string]*string (conversion is required by the API that I was consuming).
The Problem
In my first method, I tried to iterate over each entry in the source map, aMap and convert the string value of each entry into a string pointer and assign this pointer value to the destination map, bMap sharing the same key as aMap. I initially expected the dereferenced value held in bMap to be the same as aMap under the same key. However, it turned out that the deferenced value of bMap does not share the same value with aMap under the same key.
My questions would be:
Why does this problem happen?
I was able to resolve the issue using the second method, by first defining a function that receives a string and returns a pointer, that way I was able to correctly return the deferenced value to share the same value as aMap under the same key. Why does this method work?
Also, just curious, why is &(*v) a syntax error in Go? I also tried declaring a dummy variable val := *v, and assigning it to bMap using bMap[key] = &val but to no avail. The error said invalid indirect of v (type string)
Source Code
https://play.golang.org/p/ZG7XS2vJx0y
func main() {
aMap := make(map[string]string)
aMap["foo"] = "bar"
aMap["bar"] = "baz"
aMap["baz"] = "foo"
bMap := make(map[string]*string)
for k, v := range(aMap){
bMap[k] = &v
}
// first method
fmt.Println("1st method, map[string]*string, bMap")
for k, v := range(bMap){
fmt.Printf("bMap[%s] = %s / %s, aMap[%s] = %s\n",
k, *bMap[k], *v, k, aMap[k])
}
pString := func(v string) *string{ return &v }
for k, v := range(aMap){
bMap[k] = pString(v)
}
// second method
fmt.Println("2nd method, map[string]*string, bMap")
for k, v := range(bMap){
fmt.Printf("bMap[%s] = %s / %s, aMap[%s] = %s\n",
k, *bMap[k], *v, k, aMap[k])
}
// expected results
fmt.Println("Expected result: map[string]string, cMap")
cMap := make(map[string]string)
for k, v := range(aMap){
cMap[k] = v
}
for k, v := range(cMap){
fmt.Printf("cMap[%s] = %s / %s, aMap[%s] = %s\n",
k, cMap[k], v, k, aMap[k])
}
}
Output
1st method, map[string]*string, bMap
bMap[baz] = foo / foo, aMap[baz] = foo
bMap[foo] = foo / foo, aMap[foo] = bar
bMap[bar] = foo / foo, aMap[bar] = baz
2nd method, map[string]*string, bMap
bMap[baz] = foo / foo, aMap[baz] = foo
bMap[foo] = bar / bar, aMap[foo] = bar
bMap[bar] = baz / baz, aMap[bar] = baz
Expected result: map[string]string, cMap
cMap[baz] = foo / foo, aMap[baz] = foo
cMap[foo] = bar / bar, aMap[foo] = bar
cMap[bar] = baz / baz, aMap[bar] = baz
Thank you so much.
The problem in method 1 is that you aren't taking the address of the string, you're taking the address of the variable it's in. In Go, &v returns the address of variable v. When you have a loop like this:
for k, v := range aMap {
...
}
The variables k and v that you declare at the start of the loop are the same variables used throughout the loop. They are just assigned different values on each iteration. Within that loop &v always evaluates to the same value: the address of v. That's why all of your map entries come out to "foo": "foo" is the last value placed in v, and it's still there.
You can see this behavior in action by changing the string value. All of the map keys will change:
*bMap["foo"] = "quux"
fmt.Println(*bMap["bar"]) // prints "quux"
Method 2 works because every call of a function has its own local variables. Go guarantees that if you return the address of a local variable from a function, that variable will be allocated on the heap where it can be used as long as it's needed. So your helper function is telling Go to allocate a new string variable, copy the passed-in string to it, then return its address.
Here's another method that will work:
dMap := make(map[string]*string)
for k, v := range(aMap){
dMap[k] = new(string)
*dMap[k] = v
}
This allocates a new string variable, saves its address in the map, then copies v into it. If you're going to do this often, the helper function is probably best.
The code you tried like this:
v := "foo"
val := *v
bMap[key] = &val
doesn't work because you're saying, "v is a string; now store the value that string points to in val", but the string isn't a pointer.
The first method in the question uses the address of of the single loop variable v for all keys. The value that you see is the last value set to v.
Fix by declaring a new variable for each iteration and taking the address of that variable.
bMap := make(map[string]*string)
for k, v := range aMap {
v := v // declare new variable v initialized with value from outer v
bMap[k] = &v
}
The second method in the question also declares a new variable for each iteration in the loop. The new variable is the function argument.
This answer shows the idiomatic approach for addressing the issue. See Go FAQ: What happens with closures running as goroutines? for a discussion of the same issue in the context of closures and goroutines.

What is the difference between := and = in Go?

I am new to Go programming language.
I noticed something strange in Go: I thought that it used := and substitutes = in Python, but when I use = in Go it is also works.
What is the difference between := and =?
= is assignment. more about assignment in Go: Assignments
The subtle difference between = and := is when = used in variable declarations.
General form of variable declaration in Go is:
var name type = expression
the above declaration creates a variable of a particular type, attaches a name to it, and sets its initial value. Either the type or the = expression can be omitted, but not both.
For example:
var x int = 1
var a int
var b, c, d = 3.14, "stackoverflow", true
:= is called short variable declaration which takes form
name := expression
and the type of name is determined by the type of expression
Note that: := is a declaration, whereas = is an assignment
So, a short variable declaration must declare at least one new variable. which means a short variable declaration doesn't necessarily declare all the variables on its left-hand side, when some of them were already declared in the same lexical block, then := acts like an assignment to those variables
For example:
r := foo() // ok, declare a new variable r
r, m := bar() // ok, declare a new variable m and assign r a new value
r, m := bar2() //compile error: no new variables
Besides, := may appear only inside functions. In some contexts such as the initializers for "if", "for", or "switch" statements, they can be used to declare local temporary variables.
More info:
variable declarations
short variable declarations
= is just assignment
:= is declare-and-initialize construct for new vars (at least one new var) inside the function block (not global):
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
:= is the "short declaration form" for declaring and initializing variables. It does type inference on the value that you are assigning to set the variable's type.
If you attempt to assign with the short declaration form to the same variable in the same scope, the compiler will throw an error.
Be on the lookout for the short declaration form "shadowing" the same variable in an enclosing scope (especially with errors)
= requires the var keyword when declaring a variable and the variable's type explicitly following the variable name. You can actually leave the = off the declaration since Go has a initial value for all types (strings are initialized as "", ints are 0, slices are empty slices). It can also be used for reassignment with just a value, ie
var s string = "a string" // declared and initialized to "a string"
s = "something else" // value is reassigned
var n int // declared and initialized to 0
n = 3
Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type.
for example:
package main
import "fmt"
func main() {
var i, j int = 1, 2
k := 3
c, python, java := true, false, "no!"
fmt.Println(i, j, k, c, python, java)
}
NOTICE: the variable declared with := can only be used inside the function block.
I took time to figure out a mistake I made that could help you to clarify the difference between := and =.
Consider the following code:
type mystruct struct {
a int
arr []int
}
func main() {
m := mystruct{}
m.arr := make([]int, 5) //compilation error because m.arr is already declared.
m.arr = make([]int, 5) //compiles
}
= is used as statically typed.
:= is used as dynamically typed.
example:
var a = 30 # statically typed and is a compile time check
b := 40 # dynamically checked.
Note the difference in := and = in range clauses as well. The following examples are adapted from the spec.
The iteration variables may be declared by the "range" clause using a form of short variable declaration (:=). In this case their types are set to the types of the respective iteration values and their scope is the block of the "for" statement; they are re-used in each iteration. If the iteration variables are declared outside the "for" statement, after execution their values will be those of the last iteration.
= range ...:
i := 2
x = []int{3, 5, 7}
for i, x[i] = range x { // i,x[2] = 0,x[0]
break
}
// now i == 0 and x == []int{3, 5, 3}
var (key string; val interface{})
m := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6}
for key, val = range m {
h(key, val)
}
// key == last map key encountered in iteration (note order of map iteration is random)
// val == map[key]
:= range ...:
var a [10]string
for i, s := range a {
// type of i is int, type of s is string
// s == a[i]
someFunction(i, s)
}
// i and s are no longer accessible here.
for i := range a { // roughly equivalent to `for i := 0; i < len(a); i++`
someFunction(i, a[i])
}
for _, s := range a {
anotherFunc(s)
}
// Above is roughly equivalent to:
{
var s string
for i := 0; i < len(a); i++ {
s = a[i]
anotherFunc(s)
}
}
// s not accessible here
The most verbose way to declare a variable in Go uses the var keyword, an explicit type, and an assignment.
var x int = 10
Go also supports a short declaration format. When you are within a function, you can
use the := operator to replace a var declaration that uses type inference.
var x = 10
x := 10
There is one limitation on :=. If you are declaring a variable at package level, you
must use var because := is not legal outside of functions.
There are some situations within functions where you should avoid :=
When initializing a variable to its zero value, use var x int. This makes it clear
that the zero value is intended.
When assigning an untyped constant or a literal to a variable and the default type
for the constant or literal isn’t the type you want for the variable, use the long var
form with the type specified. While it is legal to use a type conversion to specify
the type of the value and use := to write x := byte(20), it is idiomatic to write
var x byte = 20.
Because := allows you to assign to both new and existing variables, it sometimes
creates new variables when you think you are reusing existing ones. In those situations, explicitly declare all
of your new variables with var to make it clear which variables are new, and then
use the assignment operator (=) to assign values to both new and old variables.
While var and := allow you to declare multiple variables on the same line, only use
this style when assigning multiple values returned from a function or the comma ok
idiom.
Learning Go Jon Bondner

How to differentiate between assigning and declaring values from a function with multiple returns?

When retrieving multiple returns from a function, I get that you can declare variables for the values on the fly by using := or assign the values to already existing variables by simply using =. My issue occurs when I want to assign one of the return values to an already existing variable while declaring a new variable for the other.
I have currently solved it by only assigning the values and declaring the required variables (bar in this case) beforehand, as in this snippet:
package main
import (
"fmt"
)
func getFooAndBar() (foo string, bar string) {
return "Foo", "Bar"
}
func main() {
var foo = "default"
var condition = true
if condition {
var bar string // Would like to avoid this step if possible
foo, bar = getFooAndBar()
fmt.Println(bar)
}
fmt.Println(foo)
}
If I use := it fails to build due to:
./app.go:16: foo declared and not used
So, is it possible to somehow avoid the step declaring bar separately?
In this case you can't use the short variable declarations ":=" for redeclaring the foo variable, according to the spec:
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block with the same type, and at least one of the non-blank
variables is new. As a consequence, redeclaration can only appear in a
multi-variable short declaration. Redeclaration does not introduce a
new variable; it just assigns a new value to the original.
by eliminating ./app.go:16: foo declared and not used.
func main() {
var foo = "default"
var condition = true
if condition {
foo, bar := getFooAndBar()
fmt.Println(bar) // prints: Bar
fmt.Println(foo) // prints: Foo
// _ = foo
}
fmt.Println(foo) // prints: default
}
in this case foo is declared in the if block, this declaration will create a new variable shadowing the original foo variable in the outer block, the redeclaration of foo will happen only if you have declared foo and redeclared it with multi-variable short declaration within the same block.
func main() {
var foo = "default"
foo, bar := getFooAndBar()
fmt.Println(bar) //prints: Bar
fmt.Println(foo) //prints: Foo
}

Go fails to infer type in assignment: "non-name on left side of :="

This snippet works as expected play.golang.org/p/VuCl-OKMav
i := 10
next := 11
prev, i := i, next
However this nearly identical snippet gives non-name f.Bar on left side of := play.golang.org/p/J8NNWPugQG
type Foo struct {
Bar int
}
f := Foo{10}
next := 11
prev, f.Bar := f.Bar, next
What's special about the struct that stops type inference? Is this a bug?
It's an open issue.
Issue 6842: spec: Assigning to fields with short declaration notation
It's not really a type inference issue, it's just that the left-hand-side of := must be a list of identifiers, and f.Bar is not an identifier, so it can't be declared — not even with :='s slightly-more-permissive rules for what it can declare. See "Short variable declarations" in The Go Programming Language Specification.
From the spec's Short variable declarations section:
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block...with the same type, and at least one of the non-blank
variables is new.
So if you declare the variable inside another type (struct Foo in the example), it is disqualified by "provided they were originally declared earlier in the same block".
So the answer is to just set the pre-declared variable equal not using the := syntax to the value:
...
var prev int
prev, f.Bar = f.Bar, next
...
it is just that you already assigned f to Foo
f := Foo{100}
in this case f.Bar is 100
so to reassign it just remove the column
var prev string
f := Foo{10}
next := 11
prev, f.Bar = f.Bar, next
this will work

Resources