Go中的文件路径

Go中的文件路径,go,filepath,Go,Filepath,这是MarkSummerfield中编程的例子 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, britishAm

这是MarkSummerfield中编程的例子

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不能从适当的目录中获取文件?

您可以更改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)
    }
}

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

您可以在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)
    }
}

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

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

这就是
init()
中的代码所做的-它找到可执行文件的路径,并构造一个指向与之相关的字典的路径

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


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

在我看来,该程序在可执行文件所在的目录中需要一个名为
british american.txt
的文件

这就是
init()
中的代码所做的-它找到可执行文件的路径,并构造一个指向与之相关的字典的路径

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


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

在这段代码上运行
go fmt
将使我们更容易阅读它。您也可以在中这样做它还将有助于创建一个MCVE(请参阅),您可以编辑您的帖子-这使读者更容易阅读(这样我们就不必关注链接)。Deliri,您可以按照@topskip提到的内容制作一个MCVE吗?也就是说,这是一段最小的代码,它演示了您所看到的相同的意外行为。例如,我不认为所有的选项解析和处理“-h”来显示帮助文本都是重现问题所必需的。一个人阅读的无关代码越少,别人就越容易帮助你。这符合你的最大利益,不是吗?在我看来,你运行main.go时使用的是
go run main.go
。尝试使用
go build
,然后运行可执行文件。确保
british-american.txt
文件位于同一目录中,它不使用init函数工作,因为在该函数中,british-american变量覆盖了可执行目录running
go-fmt
,这段代码会让我们更容易阅读。您也可以在中这样做它还将有助于创建一个MCVE(请参阅),您可以编辑您的帖子-这使读者更容易阅读(这样我们就不必关注链接)。Deliri,您可以按照@topskip提到的内容制作一个MCVE吗?也就是说,这是一段最小的代码,它演示了您所看到的相同的意外行为。例如,我不认为所有的选项解析和处理“-h”来显示帮助文本都是重现问题所必需的。一个人阅读的无关代码越少,别人就越容易帮助你。这符合你的最大利益,不是吗?在我看来,你运行main.go时使用的是
go run main.go
。尝试使用
go build
,然后运行可执行文件。确保
british-american.txt
文件位于同一目录中,它在没有init函数的情况下工作,因为在该函数中,britishAmerican变量用可执行文件的目录重写