▶ 技術めも
study effective go
ifとswitchには初期化ステートメントを記述できるため、そこでローカル変数の準備を行うのが一般的です。
if err := file.Chmod(0664); err != nil {
log.Print(err)
return err
}
newについて説明します。
これはメモリの割り当てを行う組み込み関数ですが、他言語のnewの多くとは異なり、メモリの初期化ではなく、ゼロ化のみを行います。
すなわち、new(T)は、型Tの新しいアイテム用にゼロ化した領域を割り当て、そのアドレスである*T型の値を返します。
Go言語風に言い換えると、new(T)が返す値は、新しく割り当てられた型Tのゼロ値のポインタです。
コンストラクタと複合リテラル
下の例はosパッケージからの抜粋です。この例のようにゼロ値では充分でなく、コンストラクタによる初期化が必要となることがあります。
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
上のコードには冗長な部分が多く見られます。複合リテラルとは、実行する度に新しいインスタンスを生成する式であり、これを使うことで下のコードのように単純化することができます。
式 new(File) と &File{} は等価です。
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
return &File{fd, name, nil, 0}
// return &File{fd: fd, name: name}
}
make で割り当てできるのはスライス、マップ、チャネルだけであり、初期化された、すなわちゼロ値でないT型(*Tでない)の値を返します。
makeとnewを使い分ける理由は、これらの3つの型が隠蔽されたデータ構造への参照であり、このデータ構造が使用前に初期化されている必要があるためです。
マップから登録を削除するには、代入方向を変えて複数代入式の右側に論理値を指定してください。この論理値の値が偽のとき登録が削除されます。このときマップ内にキーが存在しなくても問題ありません。
timeZone["PDT"] = 0, false // 標準時に
代替フォーマット %#v を使うとどんな値でも完全なGo言語の構文形式で出力されます。
%T これは値の型を出力します。
fmt.Printf("%#v\n", timeZone)
map[string] int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200}
...パラメータには型を指定します。
func Min(a ...int) int {
min := int(^uint(0) >> 1) // intの最大値
for _, i := range a {
if i < min {
min = i
}
}
return min
}
メソッドは、特別なレシーバ( receiver )引数を関数に取ります。(t *T)
func (t *T) String() string {
return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c)
}
fmt.Printf("%v\n", t)
変数
var (
HOME = os.Getenv("HOME")
USER = os.Getenv("USER")
GOROOT = os.Getenv("GOROOT")
)
各ソースファイルにはそれぞれ必要に応じて、セットアップのためにパラメータを持たない関数initを定義することができます。
初期化処理中に実行されるスレッドは常にひとつだけです。ゴルーチンは初期化が完了するまで実行開始しません
func init() {
if USER == "" {
log.Fatal("$USER not set")
}
if HOME == "" {
HOME = "/usr/" + USER
}
if GOROOT == "" {
GOROOT = HOME + "/go"
}
// GOROOTはコマンドラインから--gorrotフラグを指定することで上書き可能
flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory")
}
メソッド
TODO
インタフェースとメソッド
// 単純なカウントサーバ
type Counter struct {
n int
}
func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctr.n++
fmt.Fprintf(w, "counter = %d\n", ctr.n)
}
// 単純なカウントサーバ
type Counter int
func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
*ctr++
fmt.Fprintf(w, "counter = %d\n", *ctr)
}