/
で区切られます。
デフォルトでインポートする
インポートには 2 つの基本的な形式、つまり単一行インポートと複数行インポートがあり、2 つのインポート方法のインポート コードの効果は一貫しています。
1) 一行インポート
単一行のインポート形式は次のとおりです。
import “package 1”
import “package 2”
2) 複数行インポート
複数行でインポートする場合、インポート内のパッケージ名の順序はインポートの効果に影響しません。形式は次のとおりです。
import(
“package 1”
“package 2”
…
)
package mylib
func Add(a, b int) int {
return a + b
}
3 行目の Add() 関数は大文字の A で始まります。これは、Add() 関数がパッケージ外で使用するためにエクスポートされることを意味します。最初の文字が小文字の場合、その文字はパッケージ内で使用され、パッケージの外では参照できません。
add.go は mylib フォルダーの下にあり、通常はフォルダーにパッケージ名と同じ名前を付け、mylib パッケージという名前を付けます。
インポートされたパッケージは、空白行を追加することでグループ化できます。通常、異なる組織からのパッケージは個別にグループ化されます。パッケージがインポートされる順序は重要ではありませんが、各グループ内では通常、文字列の順序に従って並べ替えられます。 (gofmt ツールと goimports ツールは両方とも、異なるグループによってインポートされたパッケージを個別に並べ替えることができます。)
import (
"fmt"
"html/template"
"os"
"golang.org/x/net/html"
"golang.org/x/net/ipv4"
)
パッケージのインポート後に参照パッケージ名をカスタマイズする
math/rand パッケージと crypto/rand パッケージなど、同じ名前の 2 つのパッケージを同時にインポートする場合、競合を避けるために、インポート ステートメントで同じ名前の少なくとも 1 つのパッケージの新しいパッケージ名を指定する必要があります。 。これは、インポートされたパッケージの名前変更と呼ばれます。
import (
"crypto/rand"
mrand "math/rand" // 名前をmrandに変更して衝突を避ける
)
インポートされたパッケージの名前変更は、現在のソース ファイルにのみ影響します。同じパッケージをインポートする他のソース ファイルは、インポートされたパッケージの元のデフォルト名を使用することも、完全に別の名前に変更することもできます。
インポート パッケージの名前変更は、名前の競合を解決するためだけではなく、便利な機能です。面倒な名前のパッケージをインポートする場合、特に一部の自動生成コードでは、現時点では短い名前を使用する方が便利です。パッケージ名の混乱を避けるために、インポートされたパッケージの名前を短い名前に変更する場合は、一貫性を保つことが最善です。別のパッケージ名を選択すると、ローカルの共通変数名との競合を回避することもできます。たとえば、ファイル内にすでに path という変数がある場合、「path」標準パッケージの名前を pathpkg に変更できます。
各インポート宣言ステートメントは、現在のパッケージとインポートされたパッケージ間の依存関係を明示的に指定します。 Go のビルド ツールは、循環パッケージのインポートが発生した場合にエラーを報告します。
匿名インポート パッケージ – パッケージをインポートするだけで、パッケージ内の型と値は使用しません
パッケージ内の構造体や型を使用せずにパッケージのみをインポートし、パッケージ内の関数を呼び出さない場合は、匿名インポート パッケージを使用できます。形式は次のとおりです。
import (
_ "パッケージへのパス"
)
このうち、 path/to/package はインポートするパッケージ名を示し、アンダースコア_
は匿名インポートパッケージを示します。
匿名でインポートされたパッケージは、他の方法でパッケージをインポートするのと同じように、インポートされたパッケージを実行可能ファイルにコンパイルします。同時に、パッケージのインポートによって init() 関数呼び出しもトリガーされます。
プログラム開始前のパッケージの初期化エントリ: init
要件によっては、プログラムの起動時に、プログラムが参照するすべてのパッケージの初期化関数を一律に呼び出す必要がある要件の設計において、これらの初期化関数を開発者が手動で呼び出す必要がある場合、この処理でエラーや漏れが発生する可能性があります。参照されたパッケージ内で、パッケージの作成者にコードの起動が通知され、プログラムの起動時にパッケージ内のコードの初期化が行われることを期待します。
例えば、数学ライブラリにおける三角関数の計算の実行効率を向上させるために、プログラム起動時にあらかじめ三角関数の値をメモリ上のインデックステーブルに組み込んで、外部プログラムを実行することができます。テーブルを参照することで三角関数の値をすぐに取得できます。ただし、三角関数インデックステーブルの初期化関数の呼び出しは、外部から三角関数を使用するすべての開発者が呼び出すことを想定しているわけではなく、プログラムの起動時に三角関数パッケージに通知できる仕組みが三角関数パッケージ内にある場合には、であれば、初期化の問題は解決できます。
Go 言語は、上記の問題に対して非常に便利な機能、init() 関数を提供します。
init() 関数の特徴は次のとおりです。
- 各ソース コードでは 1 つの init() 関数を使用できます。
- init() 関数は、プログラムの実行前 (main() 関数の実行前) に自動的に呼び出されます。
- 呼び出し順序は main() で参照されるパッケージであり、深さ優先の順序で初期化されます。
たとえば、main→A→B→C というパッケージ参照関係があると仮定すると、これらのパッケージの init() 関数呼び出しシーケンスは次のようになります。
C.init→B.init→A.init→main
例証します:
- 同じパッケージ内の複数の init() 関数の呼び出し順序は予測できません。
- init() 関数は他の関数から呼び出すことはできません。
Go 言語パッケージは、メイン パッケージから始めて参照するすべてのパッケージをチェックします。各パッケージには他のパッケージも含まれている場合があります。 Go コンパイラは、ツリー状のパッケージ参照関係を構築し、参照順序に従ってコンパイル順序を決定し、これらのパッケージのコードを順番にコンパイルします。
実行時には、最後にインポートされたパッケージが最初に初期化され、init() 関数を呼び出します。
次のコードを通じて、パッケージの初期化シーケンスを理解します。
package main
import "book/chapter01/pkg1"
func main() {
pkg1.ExecPkg1()
}
コードの説明は次のとおりです。
- 3 行目は pkg1 パッケージをインポートします。
- 7 行目では、pkg1 パッケージの ExecPkg1() 関数を呼び出します。
package pkg1
import (
"book/chapter01/pkg1"
"fmt"
)
func ExecPkg1() {
fmt.Println("ExecPkg1")
pkg2.ExecPkg2()
}
func init() {
fmt.Println("pkg1 init")
}
コードの説明は次のとおりです。
- 行 4 は pkg2 パッケージをインポートします。
- 8 行目で ExecPkg1() 関数が宣言されています。
- 12 行目では、pkg2 パッケージの ExecPkg2() 関数を呼び出します。
- 15 行目では、pkg1 パッケージが初期化されるときに、pkg1 init を出力します。
package pkg2
import "fmt"
func ExecPkg2() {
fmt.Println("ExecPkg2")
}
func init() {
fmt.Println("pkg2 init")
}
コードの説明は次のとおりです。
- 5 行目で ExecPkg2() 関数が宣言されています。
- 10 行目では、pkg2 パッケージが初期化されるときに、pkg2 init を出力します。
コードを実行すると、出力は次のようになります。
pkg2 init
pkg1 init
ExecPkg1
ExecPkg2