Non-declaration statement outside function body in Go

VariablesScopeGoPackageGlobal

Variables Problem Overview


I'm building a Go library for an API that offers JSON or XML formatted data.

This API requires me to request a session_id every 15 minutes or so, and use that in calls. For example:

foo.com/api/[my-application-id]/getuserprofilejson/[username]/[session-id]
foo.com/api/[my-application-id]/getuserprofilexml/[username]/[session-id]

In my Go library, I'm trying to create a variable outside of the main() func and intend to ping it for a value for every API call. If that value is nil or empty, request a new session id and so on.

package apitest

import (
    "fmt"
)

test := "This is a test."

func main() {
    fmt.Println(test)
    test = "Another value"
    fmt.Println(test)

}

What is the idiomatic Go way to declare a globally-accessible variable, but not necesarilly a constant?

My test variable needs to:

  • Be accessible from anywhere within it's own package.
  • Be changeable

Variables Solutions


Solution 1 - Variables

You need

var test = "This is a test"

:= only works in functions and the lower case 't' is so that it is only visible to the package (unexported).

A more thorough explanation

test1.go

package main

import "fmt"

// the variable takes the type of the initializer
var test = "testing"

// you could do: 
// var test string = "testing"
// but that is not idiomatic GO

// Both types of instantiation shown above are supported in
// and outside of functions and function receivers

func main() {
    // Inside a function you can declare the type and then assign the value
    var newVal string
    newVal = "Something Else"

    // just infer the type
    str := "Type can be inferred"

    // To change the value of package level variables
    fmt.Println(test)
    changeTest(newVal)
    fmt.Println(test)
    changeTest(str)
    fmt.Println(test)
}

test2.go

package main

func changeTest(newTest string) {
	test = newTest
}

output

testing
Something Else
Type can be inferred

Alternatively, for more complex package initializations or to set up whatever state is required by the package GO provides an init function.

package main

import (
	"fmt"
)

var test map[string]int

func init() {
	test = make(map[string]int)
	test["foo"] = 0
	test["bar"] = 1
}

func main() {
	fmt.Println(test) // prints map[foo:0 bar:1]
}

Init will be called before main is run.

Solution 2 - Variables

If you accidentally use "Func" or "function" or "Function" instead of "func" you will also get:

> non-declaration statement outside of function body

Posting this because I initially ended up here on my search to figure out what was wrong.

Solution 3 - Variables

We can declare variables as below:

package main

import (
       "fmt"
       "time"
)

var test = "testing"
var currtime = "15:04:05"
var date = "02/01/2006"

func main() {
    t := time.Now()
    date := t.Format("02/01/2006")
    currtime := t.Format("15:04:05")

    fmt.Println(test) //Output: testing
    fmt.Println(currtime)//Output: 16:44:53
    fmt.Println(date) // Output: 29/08/2018
}

Solution 4 - Variables

> Outside a function, every statement begins with a keyword (var, func, and so on) and so the := construct is not available.

You can read more information here: https://tour.golang.org/basics/10

Solution 5 - Variables

Short variable declarations i.e. :=, can ONLY be used within functions.

e.g.

func main() {
    test := "this is a test"
    // or
    age := 35
}

Declarations outside a function you must make use of keywords like var, func, const e.t.c depending on what you want (in this case we're using var).

Declaring a variable outside a function makes it accessible within its package.

package apitest

import (
    "fmt"
)
// note the value can be changed
var test string = "this is a test"

func main() {
    fmt.Println(test)
    test = "Another value"
    fmt.Println(test)

}

Extra info

If you want the variable to be accessible both within and outside its package, the variable has to be capitalized e.g.

var Test string = "this is a test"

this will make it accessible from any package.

Solution 6 - Variables

I got this error when I was trying to run Go app with function definition like this:

(u *UserService) func GetAllUsers() (string, error) {...} //Error code

The correct way of defining a function (receiver function) was:

func (u *UserService) GetAllUsers() (string, error) {...} //Working code

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsergsergView Question on Stackoverflow
Solution 1 - VariablesrobbmjView Answer on Stackoverflow
Solution 2 - VariablesKANJICODERView Answer on Stackoverflow
Solution 3 - VariablesWalkView Answer on Stackoverflow
Solution 4 - VariablesAlongkornView Answer on Stackoverflow
Solution 5 - Variablespickup limesView Answer on Stackoverflow
Solution 6 - VariablesSuz'l ShresthaView Answer on Stackoverflow