80

私はio/ioutil小さなテキストファイルを読むために使用しています:

fileBytes, err := ioutil.ReadFile("/absolute/path/to/file.txt")

それは問題なく動作しますが、これは正確には移植可能ではありません。私の場合、開きたいファイルは GOPATH にあります。次に例を示します。

/Users/matt/Dev/go/src/github.com/mholt/mypackage/data/file.txt

dataフォルダーはソース コードのすぐそばにあるので、相対パスを指定するだけで十分です。

data/file.txt

しかし、その後、次のエラーが発生します。

パニック: data/file.txt を開きます: そのようなファイルまたはディレクトリはありません

特にGoコードと一緒にある場合、相対パスを使用してファイルを開くにはどうすればよいですか?

(私の質問は、具体的には GOPATH に関連するファイルを開くことに関するものであることに注意してください。Goで相対パスを使用してファイルを開くのは、絶対パスの代わりに相対パスを指定するのと同じくらい簡単です。ファイルは、コンパイルされたバイナリの作業ディレクトリに対して相対的に開かれます。その場合、バイナリがコンパイルされた場所に関連するファイルを開きたい.後から考えると、これは悪い設計上の決定です.)

4

5 に答える 5

96

うーん...少し不便ですが、path/filepathパッケージにはAbs()(これまでのところ)必要なことを行うものがあります:

absPath, _ := filepath.Abs("../mypackage/data/file.txt")

次にabsPath、ファイルをロードするために使用すると、正常に動作します。

私の場合、データ ファイルはmain、プログラムを実行しているパッケージとは別のパッケージにあることに注意してください。すべてが同じパッケージに含まれている場合は、先頭の../mypackage/. このパスは明らかに相対的であるため、プログラムが異なれば構造も異なり、それに応じてこれを調整する必要があります。

Go プログラムで外部リソースを使用して移植性を維持するためのより良い方法がある場合は、別の回答を提供してください。

于 2013-06-12T17:54:18.220 に答える
47

this seems to work pretty well:

import "os"
import "io/ioutil"

pwd, _ := os.Getwd()
txt, _ := ioutil.ReadFile(pwd+"/path/to/file.txt")
于 2015-07-16T21:14:30.833 に答える
12

私はまさにこの問題を解決するためにgobundleを書きました。データ ファイルから Go ソース コードを生成し、それをバイナリにコンパイルします。その後、VFS のようなレイヤーを介してファイル データにアクセスできます。完全に移植可能で、ファイル ツリー全体の追加、圧縮などをサポートします。

欠点は、ソース データから Go ファイルを構築するための中間ステップが必要なことです。私は通常、これにmakeを使用します。

バイトを読み取って、バンドル内のすべてのファイルを反復処理する方法は次のとおりです。

for _, name := range bundle.Files() {
    r, _ := bundle.Open(name)
    b, _ := ioutil.ReadAll(r)
    fmt.Printf("file %s has length %d\n", name, len(b))
}

私のGeoIPパッケージで実際の使用例を見ることができます。はMakefileコードを生成geoip.goし、VFS を使用します。

于 2013-06-14T02:29:06.333 に答える
4

Alec Thomas が The Answer を提供したと思いますが、私の経験では、絶対確実ではありません。リソースをバイナリにコンパイルする際に私が抱えていた問題の 1 つは、アセットのサイズによっては、コンパイルに大量のメモリが必要になる場合があることです。小さい場合は、おそらく心配する必要はありません。私の特定のシナリオでは、1MB のフォント ファイルにより、コンパイルに約 1GB のメモリが必要になりました。Raspberry Pi で取得できるようにしたかったので、これは問題でした。これは Go 1.0 の場合です。Go 1.1 で改善された可能性があります。

そのため、その特定のケースでは、go/buildパッケージを使用して、インポート パスに基づいてプログラムのソース ディレクトリを見つけることにしました。もちろん、これにはターゲットがGOPATH設定されていて、ソースが利用可能である必要があります。したがって、すべての場合に理想的なソリューションではありません。

于 2013-06-14T16:54:02.920 に答える