请教一个包导入问题,百思不得解 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
wewin
V2EX    Go 编程语言

请教一个包导入问题,百思不得解

  •  
  •   wewin 2019-06-19 08:37:17 +08:00 3295 次点击
    这是一个创建于 2306 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目结构如下:

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

    请问是否有人知道是什么原因?

    11 条回复    2019-06-24 08:51:40 +08:00
    freestyle
        1
    freestyle  
       2019-06-19 08:44:33 +08:00 via iPhone   1
    这不是包导入的问题, file, _ := os.Open("config.json") 你用的是相对路径,会从运行的工作目录(执行 go run main.go 的目录)下查找,实际上代码运行到这一步就出错了,找不到文件. 配置文件路径应该用函数参数去传递,而不是写死在函数里面. 要正确处理 error.
    wewin
        2
    wewin  
    OP
       2019-06-19 08:52:46 +08:00
    @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 信息打印出来了。

    感谢!
    donething
        3
    donething  
       2019-06-19 13:10:14 +08:00 via Android
    再挑个次要问题,defer file.Close()应该放在 if err != nil 之后
    wewin
        4
    wewin  
    OP
       2019-06-19 14:08:47 +08:00
    @donething 这是为什么呢?`defer` 语句不是在方法返回前触发的吗?
    donething
        5
    donething  
       2019-06-19 15:10:57 +08:00 via Android
    @wewin 如果打开文件若有错误发生,就不需要调用 file.Close(),所以写在 if err!=nil 语句后面。
    wewin
        6
    wewin  
    OP
       2019-06-19 18:57:23 +08:00
    @donething 你的意思是这样?
    ```
    if err != nil {

    }
    ```
    wewin
        7
    wewin  
    OP
       2019-06-19 18:59:09 +08:00
    @donething 你的意思是这样?
    ```
    if err != nil {
    defer file.close()
    }
    ```
    donething
        8
    donething  
       2019-06-19 19:07:23 +08:00 via Android
    if err != nil {
    return err
    }
    defer file.close()
    labulaka
        9
    labulaka  
       2019-06-20 11:07:26 +08:00 via Android
    任何时候别忽略 err
    anonymous256
        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 了,比较偷懒的写法
    wewin
        11
    wewin  
    OP
       2019-06-24 08:51:40 +08:00
    @donething 不错,经过测试发现自己对 defer 返回前调用理解有误。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5402 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 42ms UTC 09:12 PVG 17:12 LAX 02:12 JFK 05:12
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86