Go中的文件路径

时间:2015-01-29 07:19:13

标签: go filepath

所以这是Mark Summerfield编写的“Go in Go”中的例子。

package main

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
)

var britishAmerican = "british-american.txt"

func init() {
    dir, _ := filepath.Split(os.Args[0])
    britishAmerican = filepath.Join(dir, britishAmerican)
}

func main() {
    rawBytes, err := ioutil.ReadFile(britishAmerican)
    if err != nil {
        fmt.Println(err)
    }
    text := string(rawBytes)

    usForBritish := make(map[string]string)

    lines := strings.Split(text, "\n")
    fmt.Println(lines)
    for _, line := range lines {
        fields := strings.Fields(line)
        if len(fields) == 2 {
            usForBritish[fields[0]] = fields[1]
        }
    }
    fmt.Println(usForBritish)
}

当我在init()func注释掉的情况下运行此代码时,它完全正常。如果我把它留在里面,我会收到这个错误:

open /var/folders/l6/rdqtyrfd303dw1cz8qvlfcvc0000gn/T/go-    build652175567/command-line-arguments/_obj/exe/british-american.txt: no     such file or directory exit status 1  

我的问题是,为什么init() func没有从相应的目录中获取文件?

2 个答案:

答案 0 :(得分:3)

您可以在init函数中更改变量britishAmerican。如果没有init(),程序将在当前目录中查找(没有给出路径,只有文件名)。使用init(),它会查找可执行文件所在的路径(os.Args[0])。对于go run main.go,具有可执行文件的目录不是当前工作目录。

您应该使用go build构建二进制文件然后运行它,或者您应该告诉我们您想要实现的目标(由@RoninDev编写)。


我提到过的MCVE看起来像这样:

package main

import (
    "io/ioutil"
    "log"
    "os"
    "path/filepath"
)

var filename = "foo.txt"

func init() {
    // change to true and things break
    if false {
        dir, _ := filepath.Split(os.Args[0])
        filename = filepath.Join(dir, filename)
    }
}

func main() {
       // requires a file 'foo.txt' in the current directory
    _, err := ioutil.ReadFile(filename)
    if err != nil {
        log.Fatal(err)
    }
}

它(当然)可以更短,但这应该足以让社区中的其他人看到正在发生的事情。

答案 1 :(得分:2)

在我看来,程序期望可执行文件所在的目录中有一个名为british-american.txt的文件。

这就是init()中的代码所做的事情 - 它找到了可执行文件的路径,并构建了相对于该字典的字典路径。

我可以从您的错误消息中看到您正在使用go run来运行代码。这在/tmp中生成一个临时可执行文件并运行它。如果您保留init()代码,那么它将在/tmp目录中查找字典,但它无法找到它。如果您取出init()代码,它将在当前目录中查找字典并且它将成功。

如果你想按照作者的意图使用它,那么使用go build构建一个二进制文件,然后运行它 - 这将有效。