在Go语言中,在函数体外部使用非声明语句是不允许的。

huangapple go评论89阅读模式
英文:

Non-declaration statement outside function body in Go

问题

我正在构建一个用于处理提供JSON或XML格式数据的API的Go库。

该API要求我每隔15分钟左右请求一个session_id,并在调用中使用它。例如:

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

在我的Go库中,我试图在main()函数之外创建一个变量,并打算在每个API调用中获取其值。如果该值为nil或空,就请求一个新的session id,以此类推。

package apitest

import (
    "fmt"
)

var test string = "This is a test."

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

在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

答案1

得分: 114

你需要

var test = "This is a test"

:= 只能在函数中使用,而且小写的 't' 是为了只在包内可见(未导出)。

更详细的解释

test1.go

package main

import "fmt"

// 变量的类型由初始化值确定
var test = "testing"

// 你也可以这样写:
// var test string = "testing"
// 但这不符合 Go 的惯例用法

// 上述两种实例化方式都适用于函数内部和函数接收器内部

func main() {
    // 在函数内部,你可以先声明类型,然后再赋值
    var newVal string
    newVal = "Something Else"

    // 也可以直接推断类型
    str := "Type can be inferred"

    // 修改包级别变量的值
    fmt.Println(test)
    changeTest(newVal)
    fmt.Println(test)
    changeTest(str)
    fmt.Println(test)
}

test2.go

package main

func changeTest(newTest string) {
	test = newTest
}

输出

testing
Something Else
Type can be inferred

另外,为了进行更复杂的包初始化或设置包所需的任何状态,GO 提供了一个 init 函数。

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) // 输出 map[foo:0 bar:1]
}

init 函数会在 main 函数运行之前被调用。

英文:

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.

答案2

得分: 35

如果你不小心使用了"Func"、"function"或"Function"而不是"func",你也会得到以下错误信息:

在函数体外的非声明语句

我发布这个信息是因为我最初在搜索中遇到了相同的问题,想找出问题出在哪里。

英文:

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.

答案3

得分: 6

短变量声明,即:=只能在函数内部使用。

例如:

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

在函数外部声明变量时,必须使用关键字var、func、const等,具体取决于你想要的内容(在这个例子中我们使用了var)。

在函数外部声明变量可以使其在包内可访问。

package apitest

import (
    "fmt"
)

// 注意这个值是可以改变的
var test string = "this is a test"

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

额外信息

如果你希望变量在其所在的包内外都可访问,变量的首字母必须是大写,例如:

var Test string = "this is a test"

这将使其在任何包中都可访问。

英文:

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.

答案4

得分: 3

我们可以按照以下方式声明变量:

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) //输出:testing
    fmt.Println(currtime) //输出:16:44:53
    fmt.Println(date) //输出:29/08/2018
}
英文:

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
}

答案5

得分: 3

在函数外部,每个语句都以关键字(varfunc等)开头,因此:=构造不可用。

你可以在这里阅读更多信息:https://tour.golang.org/basics/10

英文:

> 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

答案6

得分: 1

当我尝试运行具有以下函数定义的Go应用程序时,出现了这个错误:

(u *UserService) func GetAllUsers() (string, error) {...} //错误代码

正确的函数定义方式(接收器函数)是:

func (u *UserService) GetAllUsers() (string, error) {...} //可运行的代码
英文:

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

huangapple
  • 本文由 发表于 2013年12月11日 08:38:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/20508356.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定