2017-04-24 6 views
0

この実験を参照してください。パッケージ文と.goファイルのディレクトリとの関係

~/go/src$ tree -F 
. 
├── 1-foodir/ 
│   └── 2-foofile.go 
└── demo.go 

1 directory, 2 files 

~/go/src$ cat demo.go 
package main 

import (
    "fmt" 
    "1-foodir" 
) 

func main() { 
    fmt.Println(foopkg.FooFunc()) 
} 

~/go/src$ cat 1-foodir/2-foofile.go 
package foopkg 

func FooFunc() string { 
    return "FooFunc" 
} 

~/go/src$ GOPATH=~/go go run demo.go 
FooFunc 

私は常にパッケージ名をインポートすると考えました。しかし、上記の例の は、パッケージディレクトリ名("1-foodir") を実際にインポートしていますが、そのパッケージ内にエクスポートされた名前を呼び出す際に、Goファイル(foopkg.FooFunc)で宣言された パッケージ名を使用しています。

これは、JavaとPythonの世界から来てくれた私のような初心者のために混乱しています。 ここで、ディレクトリ名自体はパッケージに定義されている モジュール/クラスを修飾するために使用されるパッケージ名です。

importステートメントと の使用方法に違いがあるのは、パッケージに定義されている名前ですか? Goについてのこれらのことの背後にある規則 を説明できますか?

答えて

2

あなたの言ったことが真実ならば、関数呼び出しは実際にはfoopkg.FooFunc()の代わりに1-になります。代わりに2-foofile.goでパッケージ名を確認し、foopkgとしてインポートします。パッケージの名前は、有効な識別子であれば、.goファイルの先頭にある単語packageの後ろに正確に来るからです。

ディレクトリの唯一の使用は、同じパッケージ名を共有する一連のファイルを収集することです。これはスペック

同じPackageNameには、パッケージの実装を形成する共有ファイルのセットに反復されます。実装では、パッケージのすべてのソースファイルが同じディレクトリに存在する必要があります。

ディレクトリではパッケージ名と一致するのが一般的ですが、必ずしもそうである必要はなく、多くの場合サードパーティのパッケージではありません。 stdlibはこのコンベンションに固執しています。

ここでディレクトリを実行すると、がインポートされます。あなたは、限り、彼らは異なるインポートパスを持っていたとして、あなたの単一のバイナリに「FOO」という名前の2つのパッケージを持っているすなわち

/some/path/1/foo/some/path/2/foo

そして、私たちは本当にしゃれ取得し、我々が望んでいたものは何でも輸入エイリアスすることができます可能性があり例えば、私は

import (
    bar "/some/path/1/foo" 
    baz "/some/path/2/foo" 
) 

を行うことができ再度パッケージ名は一意である必要があるため、これは働く理由はありませんが、パッケージのインポートパスは一意でなければなりません。

このステートメントから収集するもう1つの洞察は、ディレクトリ内に2つのパッケージ名を持つことができないことです。 goコンパイラはcannot load packageというエラーを返し、それはfound packages foo (foo.go) and bar (bar.go)となります。

詳細については、https://golang.org/doc/code.html#PackageNamesを参照してください。

1

は大雑把理由のために:

  1. パッケージは、ソースコードの先頭にパッケージ句、package thepackagenameによって設定された「名前」を持っています。

  2. パッケージをインポートするには、かなり不透明な文字列、つまりインポート宣言のインポートパスがあります。

最初の名前とその名前の2番目の検索方法です。 1つはプログラマ用、2つ目はコンパイラ/ツールチェーン用です。 "/some/hierarchical/location"

で見つかったパッケージをインポートし、それが

のような文で robotのような単純な名前だことにより、そのパッケージを参照してください

を述べること(コンパイラやプログラマのための)非常に便利です。

robot.MoveTo(3,7) 

このパッケージを次のように使用してください。

/some/hierarchical/location.MoveTo(3.7) 

は、法的なコードではなく、判読可能でも明確でも便利でもありません。 しかし、コンパイラ/ツールチェーンの場合、インポートパスに構造があり、任意のパッケージの場所、つまりファイルシステム内の場所だけでなく、その場所を表すことができればいいです。アーカイブ内またはリモートマシン上、またはorまたは。

Goコンパイラとgoツールがあります。 Goコンパイラとgoツールは異なるものです。Goツールは、Goコンパイラや言語仕様に必要なものよりも、コード、ワークスペース、パッケージのレイアウト方法に制限を課しています。 (Goコンパイラは異なるディレクトリのファイルを問題なくコンパイルできます)

goツールは、パッケージのソースファイルが1つのファイルシステムに存在するディレクトリと常識では、このディレクトリを「パッケージのように」指定する必要があります。

+0

私の答えで私はそれを逃した道具のビットについて1つプラス。 – darethas

関連する問題