Goコードレビューでよく指摘されるやつ

● Goコードレビューでよく指摘されるやつ

https://go.dev/wiki/CodeReviewComments

Goコードレビューでよく指摘される項目のチートシート。網羅的なスタイルガイドではなく、レビューで頻出するコメントの早見表。

フォーマット・コメント

  • Gofmt: 機械的なスタイルはgofmt(またはgoimports)に任せる
  • コメント文: エクスポートする宣言のコメントは完全な文で。名前から始めてピリオドで終える
  • Docコメント: トップレベルのエクスポート名には必ず付ける
  • パッケージコメント: package宣言の直前、空行なしで書く

命名規則

  • Mixed Caps: MAX_LENGTHではなくmaxLength
  • 頭字語: URL/IDは大文字小文字を統一(UrlはNG)
  • 変数名: スコープが狭いほど短く(lineCountよりc)。宣言から離れるほど説明的に
  • レシーバ名: 型の1〜2文字の略称。self/thisのような汎用名は避ける
  • パッケージ名: util/commonなど無意味な名前を避ける

エラー処理

  • エラーは握りつぶさない: _で無視しない
  • エラー文字列: 大文字で始めない、句読点で終えない
  • 正常系を先に: エラー処理を先に片付け、正常系のインデントを浅く保つ
  • バンド内エラー禁止: -1やnilではなく(value, ok)や(value, err)の複数戻り値で表現
  • panicを使わない: 通常のエラー処理には使わない

設計・API

  • Context: 第一引数として明示的に渡す。構造体フィールドにしない
  • インターフェース: 利用側パッケージに定義する。モック目的だけの定義はしない
  • 名前付き戻り値: godocでの見え方を考え、本当に必要な時だけ使う
  • ポインタは節約目的で使わない: サイズが変わらない値をポインタにしない
  • 値/ポインタレシーバ: 迷ったらポインタ。ミューテックスを含む構造体は必ずポインタ
  • 同期関数を優先: 非同期より同期関数の方がテストしやすく安全

その他

  • コピー注意: ポインタ型にメソッドが紐づく型はコピーしない
  • 乱数: キー生成にmath/randは使わずcrypto/randを使う
  • 空スライス: []string{}よりvar t []string(nil)を優先
  • Goroutineの寿命: いつ終了するか明確にする
  • 行の長さ: 厳密な制限はなく、意味的な理由で改行する
  • テスト失敗メッセージ: got != wantの順でわかりやすく出力する

参考 : Go の interface は構造体の利用側が定義すると言う話 – もばらぶエンジニアブログ

No.2773
09/04 16:52

edit

Goenv の代わりに mise で Go のバージョンを管理する。

一旦もともと入っている Go 言語を削除します。

・HomebrewでインストールしたGoの削除

Homebrew経由でインストールされている複数のGoバージョンをすべて強制削除します。

brew uninstall --force go

・直接インストールしたGo(公式パッケージ版)の削除

公式のインストーラーで入れたGoの実体と、システムがPATHを通すために作成したファイルを削除します。

Goの実体ディレクトリを削除

sudo rm -rf /usr/local/go
sudo rm /etc/paths.d/go

mise でGoをインストールする

# Go 1.26 のインストール
mise install go@1.26

# グローバル(マシン全体)のデフォルトバージョンを 1.26 に設定
mise use -g go@1.26

vscode , cursor で Go 関連の拡張機能をアップグレードする。

Command + shift + P → Go Install/Update Tools を選択
No.2748
06/09 10:34

edit

Goのジェネリクス

Go の interface{} → any

Go 1.18 でジェネリックス(Generics)が導入され、それに合わせて any が追加された。

any は新しい型ではなく、interface{} のエイリアスである。

type any = interface{}

そのため、以下は完全に同じ意味になる。

map[string]interface{}
map[string]any

現在は Go の公式コードやコミュニティでも any が推奨されることが多く、 モダンな Go コードでは interface{} より any がよく使われるので、覚えておきましょう。

No.2747
06/09 09:28

edit

Go ECHO で ログを JSON形式、LTSV形式にする

// LoggerミドルウェアをJSON形式で
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    Format: `{"time":"${time_rfc3339}","method":"${method}","uri":"${uri}","status":${status},"latency_ms":${latency_ms},"remote_ip":"${remote_ip}","error":"${error}"}` + "\n",
}))
// LoggerミドルウェアをLTSV形式で
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    Format: "time:${time_rfc3339}\tmethod:${method}\turi:${uri}\tstatus:${status}\tlatency_ms:${latency_ms}\tremote_ip:${remote_ip}\terror:${error}\n",
}))
No.2668
10/14 22:40

edit

Go ECHO の Recoverミドルウェア

	// Recoverミドルウェア(panicをキャッチしてログ出力)
	e.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{
		LogLevel: log.ERROR,
	}))
No.2667
10/14 22:37

edit

Goのビルドタグ

● Goのビルドタグとは?

Go のソースコードに「このファイルをどの条件でビルド対象に含めるか」を指定する仕組みです。
複数の環境(OS、アーキテクチャ、機能の有無など)で異なるソースを切り替えるのに使います。

● Goのビルドタグの書き方

//go:build staging

● 例えば以下のビルドタグを設定するとどうなるのか?

//go:build staging

とすると、staging が 有効な場合のみこのファイルが読み込まれます。

● IntelliJ や Goland で設定する

添付ファイル1
go-tags.png ( 114.0 KBytes ) ダウンロード
No.2650
09/10 13:08

edit

添付ファイル

MacにGo をインストールする

● MacにGo をインストールする

brew install go

● GOROOT と GOPATH と を確認します。

go env GOROOT
go env GOPATH

go の環境変数全てを確認する

go env

● gopls(Language Server)のインストール

go install golang.org/x/tools/gopls@latest

goplsがインストールされた場所を確認

ls -la $(go env GOPATH)/bin/gopls

GOPATHのbinディレクトリを確認

echo $(go env GOPATH)/bin

PATHに含まれているか確認

echo $PATH | grep -o "$(go env GOPATH)/bin"
.bash_profile などに追記する
code .bash_profile 

.bash_profile

# goplus
export PATH=$PATH:$(go env GOPATH)/bin

● goplsコマンドの確認

gopls version
golang.org/x/tools/gopls v0.20.0
No.2630
08/07 23:43

edit

Go の New 命名規則

● Go の New 命名規則

・関数名としての NewXxx

New というプレフィックスを持つ関数名は、特定の型や構造体の新しいインスタンスを生成するためのコンストラクタ関数として使われます。

func NewXxx(parameters) *Xxx {
    return &Xxx{...} // Xxx構造体のポインタを返す
}

例

type person struct {
	height float32
	weight float32
}

func NewPerson(height, weight float32) *person{
	return &person{height: height, weight: weight}
}

func main() {
	p := NewPerson(182.0, 75.5)
	fmt.Println(p) // &{182 75.5}
}

引用: https://qiita.com/gold-kou/items/4494f8b69b8fa53d5e93

・ Newの代わりにCreateは使える?

CreateXxx が使われる場合
CreateXxx は、オブジェクトやリソースを生成・初期化するプロセスがより複雑な場合や、外部システムとの関わりがある場合に使用される傾向があります。例えば、以下のようなケースです:

外部リソースの作成が関与する場合

ファイル、ネットワーク接続、データベースエントリなど。
外部リソースの作成に失敗する可能性があり、エラーを返す必要がある。
生成プロセスが単純ではない場合

内部で複数のステップが必要だったり、リソースの確保や設定が絡む場合。
明確に「作成」という意味を強調したい場合

「新しいインスタンスを返す」以上の動作を表現したいとき。

No.2571
11/22 19:39

edit