项目结构如下:
decoder
├── config.json
└── decoder.go
config.json 文件内容
{
"ServerInfo": {
"Host": "127.0.0.1:8888"
},
"RedisInfo": {
"Host": "127.0.0.1:6379",
"MaxIdle": 16,
"MaxActive": 0,
"IdleTimeout": 300
}
}
decoder.go 文件内容
package main
import (
"encoding/json"
"fmt"
"os"
"time"
)
type Config struct{}
type ConfigurationType struct {
ServerInfo ServerInfoType
RedisInfo RedisInfoType
}
type ServerInfoType struct {
Host string
}
type RedisInfoType struct {
Host string
MaxIdle int
MaxActive int
IdleTimeout time.Duration
}
var Configuration = ConfigurationType{}
func (this Config) InitConfig() {
file, _ := os.Open("config.json")
defer file.Close()
decoder := json.NewDecoder(file)
Configuration = ConfigurationType{}
err := decoder.Decode(&Configuration)
if err != nil {
fmt.Println("Error: ", err)
}
fmt.Printf("Configuration: %v\n", Configuration)
}
func main() {
conf := Config{}
conf.InitConfig()
}
这种情况下我运行:go run decoder.go
, 输出结果如下:
Configuration: {{127.0.0.1:8888} {127.0.0.1:6379 16 0 300ns}}
但是我把这个 main 包改为 decoder 包,项目结构调整如下
.
├── decoder
│ ├── config.json
│ └── decoder.go
└── main.go
config.json 文件内容
{
"ServerInfo": {
"Host": "127.0.0.1:8888"
},
"RedisInfo": {
"Host": "127.0.0.1:6379",
"MaxIdle": 16,
"MaxActive": 0,
"IdleTimeout": 300
}
}
decoder.go 文件内容
package decoder
import (
"encoding/json"
"fmt"
"os"
"time"
)
type Config struct{}
type ConfigurationType struct {
ServerInfo ServerInfoType
RedisInfo RedisInfoType
}
type ServerInfoType struct {
Host string
}
type RedisInfoType struct {
Host string
MaxIdle int
MaxActive int
IdleTimeout time.Duration
}
var Configuration = ConfigurationType{}
func (this Config) InitConfig() {
file, _ := os.Open("config.json")
defer file.Close()
decoder := json.NewDecoder(file)
Configuration = ConfigurationType{}
err := decoder.Decode(&Configuration)
if err != nil {
fmt.Println("Error: ", err)
}
fmt.Printf("Configuration: %v\n", Configuration)
}
main.go 文件内容
package main
import "initTest/decoder"
func main() {
t := decoder.Config{}
t.InitConfig()
}
测试运行 go run main.go
报错如下:
Error: invalid argument
Configuration: {{} { 0 0 0s}}
请问是否有人知道是什么原因?
1
freestyle 2019-06-19 08:44:33 +08:00 via iPhone 1
这不是包导入的问题, file, _ := os.Open("config.json") 你用的是相对路径,会从运行的工作目录(执行 go run main.go 的目录)下查找,实际上代码运行到这一步就出错了,找不到文件. 配置文件路径应该用函数参数去传递,而不是写死在函数里面. 要正确处理 error.
|
2
wewin OP @freestyle 哎哟,我去,被闪了腰。现在用的语言文件找不到直接是跑出了异常,go 语言这种直接返回 err 的还真的不太习惯。
将 decoder.go InitConfig 方法改了: ``` ... func (this Config) InitConfig() { file, err := os.Open("config.json") defer file.Close() if err != nil { fmt.Printf("Open file error: %v\n", err) } decoder := json.NewDecoder(file) Configuration = ConfigurationType{} err = decoder.Decode(&Configuration) if err != nil { fmt.Println("Error: ", err) } fmt.Printf("Configuration: %v\n", Configuration) } ``` 将读文件的 err 信息打印出来了。 感谢! |
3
donething 2019-06-19 13:10:14 +08:00 via Android
再挑个次要问题,defer file.Close()应该放在 if err != nil 之后
|
5
donething 2019-06-19 15:10:57 +08:00 via Android
@wewin 如果打开文件若有错误发生,就不需要调用 file.Close(),所以写在 if err!=nil 语句后面。
|
8
donething 2019-06-19 19:07:23 +08:00 via Android
if err != nil {
return err } defer file.close() |
9
labulaka 2019-06-20 11:07:26 +08:00 via Android
任何时候别忽略 err
|
10
anonymous256 2019-06-20 23:20:21 +08:00 via Android
我也很烦 golang 每次都要判断 err,所以一般就写个函数
func checkErr(err error){ if err != nil{ // do something } } 这样每次都只直接调用这个 checkErr,而不是判断它是不是等于 nil 了,比较偷懒的写法 |