duanhai7274 2017-09-09 20:58
浏览 49

为什么Go + build标签会引入范围问题?

I am writing a web server in Go lang, which needs to read a configuration file into memory before the server starts. I am having trouble accessing my Settings type, several variables, and a function which are defined in settings.go. These need to be accessible to other files within the same package, but I keep getting 'undefined' errors, suggesting I have some sort of scope error.

Below is a minimal code example which demonstrates my issue. Each file has // +build go1.8 tags defined on the first line. With these tags present, compilation fails with the errors described below. Without these tags, compilation proceeds as expected.

main.go

// +build go1.8
package main

import (
    "myapp/srv"
)

func main() {
    srv.StartServer()
}

server.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))
}

settings.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
}

Compilation attempted with Go v1.8.3 on Fedora 26 Workstation by running go build from the project directory located at $GOPATH/src/myapp.

Errors:

./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

All of the above are defined in settings.go however, which to my knowledge should be included in the package when I execute go build. Any help would be appreciated.

Project structure:

myapp/
+- srv/
|  +- server.go
|  +- settings.go
+- main.go

UPDATE: Clarified questions to reflect new knowledge. I am fairly convinced that the build tags caused the issue outlined above.

  • 写回答

1条回答 默认 最新

  • duanbi7247 2017-09-09 21:53
    关注

    Exported code from other packages has to be prefixed with the package name.

    package foo
    
    func Bar() { ... }
    

    and

    package main
    
    import foo
    
    func main() {
        foo.Bar() 
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?