loading...
Cover image for Variable Declarations in Go

Variable Declarations in Go

forstmeier profile image John Forstmeier Updated on ・2 min read

For those of you that are unfamiliar with Go syntax, there are two ways to declare local variables within a function scope - the "short" way and the "long" way.

package main

func main() {
    first := "John"                // short declaration using ":="
    var last string = "Forstmeier" // long declaration using "var"
}

In both of these instances, variables first and last are of type string but the choice of syntax is something I've always wanted more clarity on.

To my knowledge, there is no functional difference between these two approaches with the exception of declaring a slice (the former allocates memory - creating a "zero length slice" - while the latter does not) which you can see demonstrated here. Looking through some Go core source code examples, I can't make out specific patterns of when one is chosen over the other (looking specifically at in-function variables), but there are some trends that I noticed in the files I looked through (strings.go, atoi.go, and log.go) summarized in the table below.

Type Description Example
Short Assigning function results length := len(value)
Short Local variable declaration if _, ok := table[key]; ok { ... }
Short Used with range clause for k, v := range values { ... }
Short Used with "for" loop for i := 0; i < len(values); i++ { ... }
Short Copies of function arguments func name(i int) { i2 := i ... }
Short Math operator results sum := 1 + 2
Long "Parent" scope values to assign from "child" scope var count int (example)

Again, these are general observations and I did see short/long declarations used interchangeably in some cases (e.g. declaring a value to iterate on). Now, personally, I generally prefer the := for its visual appeal (the var looks ugly on repeat IMHO) but I do feel like there should be reasons to choose between the two since they're legal options within a function declaration.

Based off of what I've seen both in the Go source code and in other Go projects, I feel like this could be a good distinction:

  • Short declaration: assigning any function or operational result and for declaring variables used exclusively within a local scope
  • Long declaration: variables updated by a child scope that are processed in a parent scope

One of the big trade-offs between the two is the explicit type knowledge that comes with var, but I don't expect that to be a particular issue especially with locally declared/used variables. Also, these rules appear to be relatively in-line with current practices. Here are some examples. It's nothing terribly serious but this has always been a bit of a pet peeve of mine in Go with it being an odd "up to you" choice in an otherwise very stylistically strict language.

Discussion

markdown guide
 

For me I prefer var over :=, as using var explicitly indicates that a new variable is being declared. I use := under only three conditions:

  • When declaring a temporary variable inside a if- or for-clause. For example, if x := foo(); x { ... } and for i := 0; i < n; i++ { ... }.
  • When declaring a new variable to receive the returned value from a function, which returns more than one value. For example, when err has been declared before, I use x, err := foo() instead of var x bar; x, err = foo().
  • When shadowing a variable from the outer scope.
 

I like the approach coming from the other perspective of var being preferred. And I personally think what you've got listed here actually makes a lot of sense basically treating := as an exception to the rule of var.

 
 

I like that piece particularly this bit at the end:

In general, short variable declarations should be preferred because they are more concise than regular variable declarations/assignments.

I tend to agree with that sentiment given that := is only available inside a function, which seems to indicate it is the preferred method. var is still an option which is my primary hangup.