LoginSignup
27
11

More than 3 years have passed since last update.

Goアドベントカレンダーの穴埋め投稿です。

他の初期化処理に先駆けて、真っ先に何かをやりたいことってないですか?ありますよね?

initの呼び出し順序

Go処理系の実装依存であって、仕様はないのですが、Python同様Goは主要実装が仕様なところがあるのでこれに従って説明します。ググるといろいろ情報が出てきます。

Package initialization and program execution order

  • mainパッケージの初期化
    • 自身のパッケージの前にimportされているパッケージを初期化
    • パッケージは1度にひとつずつ初期化される
    • パッケージレベルの変数は宣言順に初期化される
    • 最後に自分の中のinitが呼ばれる
  • 最後にmain関数を呼ぶ

ここに書いてない情報としては、パッケージ内部の順序というのはファイル名の順序で規定されます。あと、init関数はパッケージ内部に同名関数をいくつも定義できますが、複数ある場合もパッケージ内部の順序(ファイル名順→ファイル内宣言順)で呼ばれます。

最速で呼ぶには

最速のファイル名を定義して、その中からimportして、その中にロジックを書くのが最速ということです。最速なのはゼロドットゴーです。

0.go
package main

import _ "github.com/shibukawa/fastest"

これのためにわざわざリポジトリを作るのはあれなので、fastestサブフォルダを作ってgo.modでreplaceでそういうパッケージがあるように見せかけます。

go.mod
module fastest_test

go 1.13

replace github.com/shibukawa/fastest => ./fastest

これが最速で呼ばれるコードです。

fastest/fastest.go
package fastest

import "log"

func init() {
    log.Println("最速で呼ばれるinit")
}

これで最速でなにかやりたいときはバッチリです!まあ実装するのがツールやらライブラリならgo.modのreplaceはやらなくても良くて、そのパッケージのサブパッケージで指定すれば良いですね。今回はコードジェネレータで置き場所が事前に決まらない、みたいなユースケースで解法を考えたのでreplace使っています。

27
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
11