What does := mean in Go? - go

I'm following this tutorial, specifically exercise 8:
http://tour.golang.org/#8
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}
Specifically what does the := mean? Searching for Go documentation is very hard, ironically.

A short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .
It is a shorthand for a regular variable declaration with initializer expressions but no types:

Keep on going to page 12 of the tour!
A Tour of Go
Short variable declarations
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 and the :=
construct is not available.)

As others have explained already, := is for both declaration, and assignment, whereas = is for assignment only.
For example, var abc int = 20 is the same as abc := 20.
It's useful when you don't want to fill up your code with type or struct declarations.

The := syntax is shorthand for declaring and initializing a variable, example f := "car" is the short form of var f string = "car"
The short variable declaration operator(:=) can only be used for declaring local variables. If you try to declare a global variable using the short declaration operator, you will get an error.
Refer official documentation for more details

:= is not an operator. It is a part of the syntax of the Short variable declarations clause.
more on this: https://golang.org/ref/spec#Short_variable_declarations

According to my book on Go, it is just a short variable declaration statement
exactly the same as
var s = ""
But it is more easy to declare, and the scope of it is less expansive. A := var decleration also can't have a type of interface{}. This is something that you will probably run into years later though

:= represents a variable, we can assign a value to a variable using :=.

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

Why does initializing just one variable in a definition fail, in golang

In calling a library function with the following signature:
func New() (*sql.DB, Sqlmock, error)
like this:
suite.db, suite.mock, err := sqlmock.New() // inside a suite method
I get error
expected identifier on left side of :=
However, when I change to this
var err error
suite.db, suite.mock, err = sqlmock.New()
the error disappears! Why does declaring k < n variables in a := assignment fail?!
:= is not assignment, it is a short variable declaration. Assignment uses e.g. the simple = operator.
As its name says: it is to declare variables. suite.db is not a variable, it is an expression, more specifically a primary expression; a selector to be exact.
The short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .
Where IdentifierList is:
IdentifierList = identifier { "," identifier } .
So you must list identifiers. One "exception" to this "declare new variables rule" is the redeclaration:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) 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.
So you are allowed to use existing variables in a short variable declaration if they were declared in the same block, and you also provide new identifiers (not just existing ones–in which case you would have to use assignment instead).
See related: Why there are two ways of declaring variables in Go, what's the difference and which to use?
When you declare err prior and change := to = it works, because the assignment does not require identifiers on the left of the assignment operator, but expressions:
Assignment = ExpressionList assign_op ExpressionList .
And as detailed above, suite.db is an expression, just like existing variables (identifiers).
:= declares a new variable "identifier". This means you are adding a named thing in your program that can be assigned a value. A struct's fields already are named, as in the golang parser knows they exist so using := makes no sense to golang in this case.
Why does declaring k < n variables in a := assignment fail?!
I'm not sure what "k < n" means, but I think you mean "why does having multiple variables on the left side of := fail?". If that's what you mean, that's not true.
x, y, z := func() (int,int,int) {return 1,2,3}()
fmt.Println(x, y, z)
works just fine. The issue is that golang cannot create an "identifier" (aka a newly named variable) for a struct field since that struct field already exists.
EDIT:
I just had a brainwave that you might have mean "why does having only some new identifiers to declare on the left side of := not work?". This also is not true.
x, y := 5, 6
fmt.Println(x, y)
x, y, z := 1, 2, 3
fmt.Println(x, y, z)
The above works just fine as well.

Idiomatic way to initialise an empty string in Go

In Go you can initialise an empty string (in a function) in the following ways:
var a string
var b = ""
c := ""
As far as I know, each statement is semantically identical. Is one of them more idiomatic than the others?
You should choose whichever makes the code clearer. If the zero value will actually be used (e.g. when you start with an empty string and concatenate others to it), it's probably clearest to use the := form. If you are just declaring the variable, and will be assigning it a different value later, use var.
var a string
It's not immediately visible that it's the empty string for someone not really fluent in go. Some might expect it's some null/nil value.
var b = ""
Would be the most explicit, means everyone sees that it's a variable containing the empty string.
b := ""
The := assigment is so common in go that it would be the most readable in my opinion. Unless it's outside of a function body of course.
There isn't a right way to declare empty variables, but there are some things to keep in mind, like you can't use the := shortcut outside of a function body, as they can with var:
var (
name string
age int64
)
I find var name = "" to be the clearest indication that you're declaring an empty variable, but I like the type explicitness of var name string. In any case, do consider where you are declaring variables. Sometimes all at once outside the function body is appropriate, but often nearest to where you actually use it is best.
rob (Pike?) wrote on a mailthread about top-level declaration
At the top level, var (or const or type or func) is necessary: each item must be introduced by a keyword for ur-syntactic reasons related to recognizing statement boundaries. With the later changes involving semicolons, it became possible, I believe, to eliminate the need for var in some cases, but since const, type, and func must remain, it's not a compelling argument.
There is a certain ambiguity in "short-variable" declarations (using :=), as to whether the variable is declared or redeclared as outlined in the specs:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) 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.
There is absolutely no difference in the generated code (with the current compiler – Go 1.7.4), and also gometalinter does not complain for any of those. Use whichever you like.
Some differences:
You can only use the short variable declaration in functions.
With short variable declaration, you can create variables of multiple types in one line, e.g.
a, b := "", 0
The following 3 apps generate identical code:
a.go
package main
import "fmt"
func main() { var a string; fmt.Println(a) }
b.go
package main
import "fmt"
func main() { var a = ""; fmt.Println(a) }
c.go
package main
import "fmt"
func main() { a := ""; fmt.Println(a) }
To verify, build each (e.g. with go build -o a), and use diff on Linux to compare the executable binaries:
diff a b && diff a c
I try to stick to the short declaration for a couple of reasons.
It's shorter
Consistency
Allocates memory for maps, slices and pointers to structs and types.
Although var a string and a := "" are the same, b := []T{} and var b []T are not the same. When dealing with slices and maps the shorter declaration will not be nil. More often then not (especially with maps) I want allocated memory.
There are few situations where var will be needed, for instance, you are calling a function that will populate a property of a type.
var err error
foo.Name, err = getFooName()
Using := syntax in the above situation will error out since foo.Name is already declared.
just
*new(string)
It's only stuff in stackoverf related to empty strings in go. So it should be here

Specman e: When colon equal sign ":=" should be used?

I saw in some Specman e code example the use of := (colon-equal sign), e.g.:
var regs_type := rf_manager.get_exact_subtype_of_instance(graphics_regs);
When and why should we use := ?
Thank you for your help.
The := means declare a variable of the type the expression on the right returns and assign it to that value. Basically, in your example, the function get_exact_subtype_of_instance(...) returns a value of type rf_struct. The regs_type variable will be declared to that type.
This code is equivalent to (but shorter than):
var regs_type : rf_struct = rf_manager.get_exact_subtype_of_instance(graphics_regs);
This syntax is particularly helpful when casting:
var foo := some_struct.as_a(FOO some_struct_type);

var vs := in Go

In the Go web server example here: http://golang.org/doc/effective_go.html#web_server
The following line of code works
var addr = flag.String("addr", ":1718", "http service address")
but changing it to
addr := flag.String("addr", ":1718", "http service address")
is a compilation error. Why? Does it have anything to do with the face that the return type of the function is *string instead of string? What difference does that make?
UPDATE: Thanks for pointing out that := is not allowed at the top level. Any idea why this inconsistency is in the spec? I don't see any reason for the behaviour to be different inside a block.
In Go, top-level variable assignments must be prefixed with the var keyword. Omitting the var keyword is only allowed within blocks.
package main
var toplevel = "Hello world" // var keyword is required
func F() {
withinBlock := "Hello world" // var keyword is not required
}
On the updated question: there is actually a difference between long and short declarations, being in that short form allows redeclaration of variables.
From 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.
field1, offset := nextField(str, 0)
field2, offset := nextField(str, offset) // redeclares offset
a, a := 1, 2 // illegal: double declaration of a or no new variable if a was declared elsewhere
So I'd say the := operator is not pure declare, but more like declare and assign.
Redeclaration in toplevel is not allowed, so neither are short declarations.
Another reason for this might be syntax simplicity. In Go all toplevel forms start with either type, var or func. Short declarations there will ruin all the cuteness.
The Go Programming Language Specification
Short variable declarations
A short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .
Short variable declarations may appear only inside functions.
In your example, changing the variable declaration statement outside a function body
var addr = flag.String("addr", ":1718", "http service address")
to a short variable declaration statement outside a function body
addr := flag.String("addr", ":1718", "http service address")
fails with compiler error "non-declaration statement outside function body."

Resources