Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-declaration statement outside function body in Go

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
like image 294
sergserg Avatar asked Dec 11 '13 00:12

sergserg


2 Answers

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.

like image 108
robbmj Avatar answered Nov 11 '22 22:11

robbmj


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.

like image 31
twitchdotcom slash KANJICODER Avatar answered Nov 11 '22 22:11

twitchdotcom slash KANJICODER