20210430のGoに関する記事は2件です。

[Go]なぜsliceの空チェックで「nil」ではなく「長さ」でチェックするのか

1. はじめに Uber Go Style Guide: nil-is-a-valid-slice Uberのスタイルガイドにある通り、sliceの空チェックは長さでチェックしなくてはいけません。 To check if a slice is empty, always use len(s) == 0. Do not check for nil. Bad func isEmpty(s []string) bool { return s == nil } Good func isEmpty(s []string) bool { return len(s) == 0 } さて、なぜsliceの空チェックで「nil」ではなく「長さ」でチェックするのか、体で覚えているだけできちんと理解していなかったので、まとめてみます。 2. sliceを「長さ」でチェックする理由 理由は、sliceが空なのにnilではない場合が発生する可能性があるため、「長さ」でチェックしないと漏れが発生するためです。 ポイントは、 ・sliceを空で宣言しても宣言の仕方によってnil sliceかempty sliceになる ・nil sliceとempty sliceともにlenとcapが0 ということです 2-1. 空で宣言しても宣言の仕方によってnil sliceかempty sliceになる 空で宣言しても、宣言の仕方によってはnil sliceかempty sliceと違いが出てきてしまい、nilチェックでは以下のパターンでチェックが漏れてしまいます。 func main() { // nil slice // こう定義するとnilになる var nilSlice []int fmt.Println(nilSlice, len(nilSlice), cap(nilSlice)) fmt.Printf("nilSlice: %s\n\n", isEmptyByNil(nilSlice)) // empty slice // こう定義するとnilにはならず、lenとcapが0となる emptySlice := []int{} fmt.Println(emptySlice, len(emptySlice), cap(emptySlice)) fmt.Printf("emptySlice: %s\n\n", isEmptyByNil(emptySlice)) } func isEmptyByNil(intSlice []int) string { if intSlice == nil { return "nil!" } else { return "not nil!" } } // 実行結果 [] 0 0 nilSlice: nil! [] 0 0 emptySlice: not nil! Go Playgroud 2-2. nil sliceとempty sliceともにlenとcapが0 nil sliceとempty sliceともにlenとcapが0という性質を利用して、長さでチェックをすれば漏れが発生することはありません。 func main() { // こう定義するとnilになる var nilSlice []int fmt.Println(nilSlice, len(nilSlice), cap(nilSlice)) fmt.Printf("nilSlice: %s\n\n", isEmptyByLen(nilSlice)) // こう定義するとnilにはならず、lenとcapが0のスライスとなる emptySlice := []int{} fmt.Println(emptySlice, len(emptySlice), cap(emptySlice)) fmt.Printf("emptySlice: %s\n\n", isEmptyByLen(emptySlice)) } func isEmptyByLen(intSlice []int) string { if len(intSlice) == 0 { return "len is zero!" } else { return "len is not zero!" } } // 実行結果 [] 0 0 nilSlice: len is zero! [] 0 0 emptySlice: len is zero! Go Playgroud 参考 Uber Go Style Guide: nil-is-a-valid-slice 技術メモ: Golangのnil sliceとnil map
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCode を使って Go のデバッガーが動くまでの設定をした

自分用メモです。 ハマった所を記載します。 基本的には以下の記事に沿う形で出来ました。 Visual Studio CodeでGo言語のデバッグ環境を整える なお、Go は初心者となり、正確ではない記述などもあるかもしれません。 環境 macOS Catalina Go 1.16.3 VS Code 1.55.2 $GOPATH を設定済み $GOPATH/bin を環境変数 $PATH へ追加済み 経緯 以下をやろうとしていました。 Goで覗くシステムプログラミングの世界 上記では IntelliJ IDEA Community版を使って Go のデバッガーを動かしています。 ただし、現状で以下の比較表を見ると IntelliJ IDEA Community版では Go 言語は使えなさそうでした。 IntelliJ IDEA その為、VS Code で同じ環境を作ることを目標としました。 ハマったポイント go get が失敗する 以下のようなエラーで go getが失敗。 $go get github.com/golang/example/hello: module github.com/golang/example/hello: Get "https://proxy.golang.org/github.com/golang/example/hello/@v/list": x509: certificate is valid for xxxxxx, not proxy.golang.org これは理由を調べると事象が発生した該当環境で proxy.golang.org がブロックされていたことが原因でした。 これについては proxy.golang.org を利用しないように以下のコマンドを実行すれば事象が回避できました。 # 設定を上書き $go env -w GOPROXY=direct # 確認 $go env |grep GOPROXY GOPROXY="direct" これは環境依存の問題なので多くの場合は事象は発生しなさそうです。 VS Code から Go を実行すると失敗する HelloWorld 用のファイルを作成。 hello.go package main import "fmt" func main() { fmt.Println("hello world") } Terminal からは成功 $go run hello.go hello world ただし、当該ファイルを VS Code で開いて VS Code 上の「Run and Debug」から実行すると以下のエラーとなる。 go: go.mod file not found in current directory or any parent directory; see 'go help modules' exit status 1 Process exiting with code: 1 launch.json を設定すればうまくいくのかもしれませんが、以下あたりを見つつ、やってみたものの、うまくいきませんでした。 golang/vscode-go エラーを改めて見ると go.mod がない、ということでこのキーワードを元に調査。 Go Modulesとマルチモジュール構成でGo Homeする方法 上記記事を参考にやってみた所、成功。 まずは Terminal で以下を実施。 # ディレクトリ作成 $mkdir hello-module # 移動 $cd hello-module # カレントディレクトリに go.mod を作る $go mod init hello-module $ls go.mod # こんなことが書いてある $cat go.mod module hello-module go 1.16 # helloworld を書く $vi hello.go # Terminal 上で動くことを確認 $ go run hello.go hello world その後、VS Code で上記フォルダ(今回の場合 hello-module) を開いて同じように「「Run and Debug」を実行した所、無事「hello world」の出力を確認。 また、ブレークポイントを設定することでデバッグなども出来る事を併せて確認。 以下などを見るとモジュール対応モードになっていることが影響しているかもしれませんが、動いたので一旦これ以上の調査は保留。 Go のモジュール管理【バージョン 1.16 改訂版】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む