我正在用 Go lang 编写一个 Web 服务器,它需要在服务器启动之前将配置文件读入内存。我在访问我的Settings
类型、几个变量和一个在settings.go
中定义的函数时遇到问题。这些需要被同一包中的其他文件访问,但我不断收到"未定义"错误,表明我有某种范围错误。
下面是一个最小的代码示例,演示了我的问题。每个文件的第一行都定义了// +build go1.8
标记。存在这些标记时,编译将失败,并出现如下所述的错误。如果没有这些标记,编译将按预期进行。
主去
// +build go1.8
package main
import (
"myapp/srv"
)
func main() {
srv.StartServer()
}
服务器.go
// +build go1.8
package srv
import (
"fmt"
"log"
"net/http"
)
func init() {
// read the server configuration file into memory
err := ReadConfig(CFGFILE)
if err != nil {
log.Fatalf("config error: %s", err)
}
}
func StartServer() {
fmt.Println("Starting server!")
fmt.Println("Using config file at: " + CFGFILE)
fmt.Println("Running on port: " + PORT)
fmt.Print(Conf.String())
log.Fatal(http.ListenAndServe(":" + PORT, nil))
}
设置.go
// +build go1.8
package srv
import (
/* Standard library packages */
"encoding/json"
"fmt"
"io/ioutil"
)
/* All settings */
type Settings struct {
/* General settings */
Title string // site title
Subtitle string // site subtitle shown on landing page
}
// allow printing of runtime config
func (s Settings) String() string {
res, err := json.MarshalIndent(s, "", " ")
var ret string
if err != nil {
ret = "Error in config."
} else {
ret = string(res)
}
return fmt.Sprintf("%s", ret)
}
// export global settings
var Conf Settings
var PORT string = "3000"
var CFGFILE string = "config.json"
func ReadConfig(file string) error {
if file == "" {
fmt.Println("Path to config file cannot be nil!")
}
buf, err := ioutil.ReadFile(file)
if err != nil {
fmt.Println(err)
}
err = json.Unmarshal(buf, &Conf)
return err
}
尝试在 Fedora 26 工作站上使用 Go v1.8.3 进行编译,方法是从位于$GOPATH/src/myapp
的项目目录中运行go build
。
错误:
./server.go:12: undefined: ReadConfig
./server.go:12: undefined: CFGFILE
./server.go:20: undefined: CFGFILE
./server.go:21: undefined: PORT
./server.go:23: undefined: Conf in Conf.String
./server.go:25: undefined: PORT
但是,以上所有内容都在settings.go中定义,据我所知,当我执行go build
时,它应该包含在包中。任何帮助将不胜感激。
项目结构:
myapp/
+- srv/
| +- server.go
| +- settings.go
+- main.go
更新:澄清问题以反映新知识。我相当确信构建标签导致了上述问题。
从其他包导出的代码必须以包名称为前缀。
package foo
func Bar() { ... }
和
package main
import foo
func main() {
foo.Bar()
}