使用不同的调用者从相对路径读取文件。

huangapple go评论139阅读模式
英文:

Read file from relative path with different callers

问题

我正在尝试从项目目录中的文件中读取内容。

我的问题是,根据调用者的不同,路径会发生变化。调用者的变化是因为我想对这段代码进行单元测试,而调用者不再是Main.go

这是我的项目结构:

使用不同的调用者从相对路径读取文件。

我尝试从中访问specialChars.txt的代码如下:

func RemoveSpecialChars(word string) string {
    file, err := ioutil.ReadFile("wordlists/specialChars.txt")
    [...]
}

这段代码在从Main.go开始时可以工作,但在从CleanupUtil_test.go开始时无法工作。为了使其在测试中工作,我需要file, err := ioutil.ReadFile("../wordlists/specialChars.txt")

我找到了像这个答案一样的解决方案:https://stackoverflow.com/a/32163888/2837489
_, filename, _, ok := runtime.Caller(0),显然也依赖于调用者。

是否有可能独立于调用函数获取项目的根路径?
或者我的代码设计有问题吗?我应该将文件路径传递给函数吗?

英文:

I'm trying to read from a file in my project's directory.

My problem is, that depending on the caller, the path changes. The caller changes, because I want to unit test this code and the caller is not Main.go anymore.

This is what my project structure looks like:

使用不同的调用者从相对路径读取文件。

The code where I try to access specialChars.txt from looks like this:

func RemoveSpecialChars(word string) string {
    file, err := ioutil.ReadFile("wordlists/specialChars.txt")
    [...]
}

This code works for the start from Main.go but not for the start from CleanupUtil_test.go. To get it working from the test I would need file, err := ioutil.ReadFile("../wordlists/specialChars.txt")

I found answers like this one: https://stackoverflow.com/a/32163888/2837489
_, filename, _, ok := runtime.Caller(0) which is obviously also dependent on the caller.

Is it possible to get the projects root path independent of the calling function?
Or is my code design wrong? Should I pass the file path into the function?

答案1

得分: 9

从Go 1.16开始,你可以使用embed包。这允许你将文件嵌入到运行的Go程序中。需要注意的是,引用的目录必须存在于嵌入文件的当前目录或其子目录中。在你的情况下,目录结构如下所示:

-- main.go
-- cleanup
  -- wordlist
    \- specialChars.txt
  CleanupUtil.go
  CleanupUtil_test.go 

你可以使用Go指令引用文件:

// CleanupUtil.go
package cleanup

import (
  "embed"
)

//go:embed wordlists/specialChars.txt
var content embed.FS

func RemoveSpecialChars(word string) string {
  file, err := content.ReadFile("wordlists/specialChars.txt")
  [...]
}

无论程序在何处执行,此程序都将成功运行。你应该能够在main.go文件和CleanupUtil_test.go文件中引用这段代码。

英文:

Starting from Go 1.16, you can use the embed package. This allows you to embed the files in the running go program. It comes with the caveat that the referenced directory needs to exist at or below the embedding file. In your case, the structure would look as follows:

-- main.go
-- cleanup
  -- wordlist
    \- specialChars.txt
  CleanupUtil.go
  CleanupUtil_test.go 

You can reference the file using a go directive

// CleanupUtil.go
package cleanup

import (
  "embed"
)

//go:embed wordlists/specialChars.txt
var content embed.FS

func RemoveSpecialChars(word string) string {
  file, err := content.ReadFile("wordlists/specialChars.txt")
  [...]
}

This program will run successfully regardless of where the program is executed. You should be able to reference this code in both your main.go file and your CleanupUtil_test.go file.

答案2

得分: 0

将文件路径作为参数传递给函数(如你上一个问题中所示)。

更多细节:

相对路径"wordlists/specialChars.txt"实际上不依赖于源文件的位置(如Main.goCleanupUtil_test.go),而是取决于你执行代码的位置。所以你可以从根目录运行测试,这样它就能正常工作。简而言之,当前工作目录是相关的。

不过,我建议指定路径,因为这样可以使你的函数更具可重用性和通用性。

也许你甚至不需要将这些信息放入文件中,而是可以简单地使用一个包含这些字符的字符串。在这种情况下,你还可以检查一下https://golang.org/pkg/regexp/#Regexp.ReplaceAll是否已经涵盖了你的用例。

英文:

Pass in the filepath as a parameter to the function (as indicated in your last question).

More details:

The relative path "wordlists/specialChars.txt" is in fact not dependent on where the source file is located (such as Main.go or CleanupUtil_test.go), but where you execute it from. So you could run your tests from your root directory and then it would actually work. In short, the current working directory is relevant.

Still, I'd recommend specifying the path, because that makes your function more reusable and universal.

Maybe you don't even need to put this information into a file, but can simply have a string containing those chars. In this case you could also check if https://golang.org/pkg/regexp/#Regexp.ReplaceAll already covers your use case.

huangapple
  • 本文由 发表于 2017年5月10日 16:54:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/43887759.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定