エラーで学ぶReactJSに引き続き、Golangで躓いたことをまとめてみました。 エラーで学ぶReactJSReactJS で遭遇したエラーと警告をまとめました。解説と解決策もあります。https://note.crohaco.net/2018/react-errors-warnings/
とはいっても完成ではなく、常にWIPとして新たに何かあれば追記していくと思います。
適当に羅列しても良かったんですが流石に長いので雑にカテゴリを区切りました。 量が多いからまだ見づらいかも..
というわけでどうぞ。 間違っている所があればコメントやTwitterで指摘ください。
役に立ったという方は拡散したり私に案件を紹介してくれてもいいんだからね!(未承諾広告)
文字列関連
rune型に一文字以外を指定する
- エラー
- rune は int32 で、 一文字以外の文字列を指定できません。 0文字(空文字) であってもエラーになります。
- cannot convert 'u0000' (type untyped number) to type string
- empty character literal or unescaped ' in character literal
- invalid character literal (more than one character)
- illegal rune literal
- rune は int32 で、 一文字以外の文字列を指定できません。 0文字(空文字) であってもエラーになります。
- 対応
- rune型に初期値を指定する場合は
0
を指定しましょう。
- rune型に初期値を指定する場合は
- NG
r := ''
- NG
r := 'test'
- OK
r := 'a'
- OK
var r rune r = 0
- 参考
文字列からruneスライスを作るときに{}で初期化しようとした
- エラー
- cannot convert "" (type untyped string) to type rune
- NG
test = []rune{""}
- OK
test = []rune("")
- 参考
%フォーマットの数に対して引数の数が一致していない
- 警告
- %フォーマットの数と引数の数が一致しないと警告が発生します。
- Printf format %s reads arg #2, but call has 1 arg
- Printf call needs 2 args but has 3 args
- %フォーマットの数と引数の数が一致しないと警告が発生します。
- NG
fmt.Printf("%s %s", "a")
- NG
fmt.Printf("%s %s", "a", "b", "c")
- OK
fmt.Printf("%s %s", "a", "b")
フォーマット関数の%sが文字列以外を受け取った
- 警告
- PrintfやSprintf の
%s
は string 型を期待しています。Sprintf format %s has arg value of wrong type *string
Printf format %s has arg value of wrong type *string
- PrintfやSprintf の
- NG
fmt.Sprintf("%s", pointer)
- OK
fmt.Sprintf("%s", *pointer)
- info
*string
(ポインタ)型であってもそのままでは扱えません。- ポインタが指す値を引数に指定しましょう。
- warning
- flagパッケージを使ってコマンドライン引数を受け取る場合、その変数はポインタ型なので注意しましょう。
関数関連
返却値のない関数の返却値を期待した
- エラー
- 返却値を返さない関数
(void型)関数の返却値を変数に格納したり参照しようとするとこのエラーが発生します。
- world() used as value
- 返却値を返さない関数
(void型)関数の返却値を変数に格納したり参照しようとするとこのエラーが発生します。
- NG
func main() { fmt.Println("Hello ", world()) } func world() { fmt.Println("World") }
- OK
func main() { fmt.Print("Hello ") world() } func world() { fmt.Println("World") }
返却値数と左辺の数があっていない
- エラー
- 関数の返却値とそれを受ける左辺の変数の数があっていないとエラーになります
- assignment mismatch: 1 variable but test returns 2 values
- 関数の返却値とそれを受ける左辺の変数の数があっていないとエラーになります
- NG
func test() (int, int) { return 1, 2 } func main() { a := test() }
- OK
func test() (int, int) { return 1, 2 } func main() { a, b := test() }
:=
での変数定義を関数外で行った
- エラー
:=
でグローバル変数を定義することはできないようです- syntax error: non-declaration statement outside function body
- 対応
- 関数内でのみ必要な変数は関数内で定義するか、 var で定義しましょう。
- NG
v := 1
- OK
func Function() { v := 1 }
- OK
var v = 1
インターフェースに定義されたメソッドが期待通りに登録されていない
- エラー
- インタフェースに定義したメソッドと名称や型が異なるとエラーになります。
- cannot use (testStruct1 literal) (value of type testStruct1) as
testInterface value in assignment: missing method test
- cannot use testStruct1 literal (type testStruct1) as type testInterface in assignment
- testStruct1 does not implement testInterface (missing test method)
- testStruct1 does not implement testInterface (wrong type for test method)
- have test(int) string, want test(int) int
- have test(string) int, want test(int) int
- cannot use testStruct1 literal (type testStruct1) as type testInterface in assignment
- cannot use (testStruct1 literal) (value of type testStruct1) as
testInterface value in assignment: missing method test
- インタフェースに定義したメソッドと名称や型が異なるとエラーになります。
- インタフェースの定義例
type testInterface interface { test(int) int } var i testInterface
- 上記は構造体に
test
というメソッドが存在することを強制するインタフェースとそれが強制された変数です - このコードを使ってOKとNGを見ていきましょう
- NG
type testStruct struct{} func main() { i = testStruct{} }
- NG
type testStruct struct{} func (t testStruct) test(s string) int { return 1 } func main() { i = testStruct{} }
- NG
type testStruct struct{} func (t testStruct) test(i int) string { return "a" } func main() { i = testStruct{} }
- OK
type testStruct struct{} func (t testStruct) test(i int) int { return 1 } func main() { i = testStruct{} }
- info
- なお、インターフェースではメソッドを定義させないことは強制できません。
関数定義と異なる数の返却値をreturnした
- エラー
- 定義した関数の返却数とreturn する値の数があっていなければエラーになります
- too many arguments to return
- missing return at end of function
- 定義した関数の返却数とreturn する値の数があっていなければエラーになります
- NG
func test() int { fmt.Println("test") // 返却値が足りない }
- NG
func test() { return 1 }
- NG
func test() int { return 1, 2 }
- OK
func test() int { return 1 }
- OK
func test() (int, int) { return 1, 2 }
公開されている関数にはコメントが書かれているべき
Golangでは大文字で始まる変数や関数は別パッケージから参照できます。
この状態をエクスポートされた状態(exported) と呼びます。フロントエンドでJSとかやってる方だとすぐ飲み込めますね。
- 警告
- 公開されている関数にコメントが書かれていないと警告が出ます
- exported function ParseCommand should have comment or be unexported
- 公開されている関数にコメントが書かれていないと警告が出ます
- 対応
- 上に
関数名[半角スペース]コメント
というフォーマットでコメントが書きましょう。
- 上に
- NG
func Test() string { }
- NG
// this is test func Test() string { }
- OK
// Test this is test func Test() string { }
printlnビルトイン関数の中でスライスを展開しようとした
- エラー
- 理由はよくわからないんですが、
println
関数の中でスライスの展開はできないようです。- invalid use of ... with builtin println
- 理由はよくわからないんですが、
- 対応
- 変数をデバッグする場合は、
fmt.Println
を使いましょう。
- 変数をデバッグする場合は、
- NG
println([]string{"a", "b"}...)
- OK
fmt.Println([]string{"a", "b"})
defer 文で関数を呼び出していない
- エラー
- defer 文は後処理として呼び出されますが、関数を呼び出し形式で指定する必要があります。
- function must be invoked in defer statement
- defer 文は後処理として呼び出されますが、関数を呼び出し形式で指定する必要があります。
- NG
defer 1
- NG
defer callback
- OK
defer callback()
- warning
- 上記はdefer文のみを書いていますが、本来は関数内に記述されている必要があります。
- 関数外に記述すると syntax error です
syntax error: non-declaration statement outside function body
型関連
インタフェース型を変換できなかった
- パニック
- interface conversion: interface {} is main.Hex, not int
- エラー
- impossible type assertion: int does not implement
- cannot have dynamic type int
- impossible type assertion: int does not implement
インタフェース型の変数を型アサーションする場合は変数に入れた値と同じ型でなければなりません。 エイリアス型の場合はエイリアス型でキャストしなければエラーになります。
今回は共通で Hex
という int
のエイリアス型とメソッドが定義されている前提で話を進めます。
type Hex int func (h Hex) String() string { return fmt.Sprintf("%x", int(h)) }
- NG
func main() { var h interface{} = Hex(100) fmt.Println(h.(int)) }
- OK
func main() { var h interface{} = Hex(100) fmt.Println(h.(Hex)) }
なお i, _ := h.(type)
のように変数に格納すればパニックは発生しません。
しかし変換できない場合はその型のゼロ値が格納されます。
ビルド時にエラーになるのは、インタフェースのメソッドセットが空でない場合です。
以下のようなインタフェースを用います。
type Stringer interface { String() string }
条件は先程と同様です。
- NG
func main() { var s Stringer = Hex(100) i, _ := s.(int) fmt.Println(i) }
- OK
func main() { var s Stringer = Hex(100) i, _ := s.(Hex) fmt.Println(i) }
レシーバの型がポインタなのに呼び出し元の型がアドレスになっていない
どうやら、インタフェースのメソッドセットを満たしているかどうかにレシーバの型が関係してくるようです。
- エラー
- レシーバをポインタ型で定義して、ポインタでない変数からメソッドを呼び出すとエラーになります。
- cannot use hello literal (type hello) as type Hello in assignment
- hello does not implement Hello (World method has pointer receiver)
- cannot use hello literal (type hello) as type Hello in assignment
- レシーバをポインタ型で定義して、ポインタでない変数からメソッドを呼び出すとエラーになります。
- 対応
- レシーバがポインタ型の場合は変数自体をポインタにしてあげるか、レシーバを値にするかのいずれかのようです。 何なんこの仕様。
- NG
package main import ( "fmt" ) func main() { var h Hello h = hello{} fmt.Println("Hello", h.World()) } type Hello interface { World() string } type hello struct {} func (h *hello) World() string { return "world" }
- OK
package main import ( "fmt" ) func main() { var h Hello h = &hello{} // ここをアドレス型にする fmt.Println("Hello", h.World()) } type Hello interface { World() string } type hello struct {} func (h *hello) World() string { return "world" }
- OK
package main import ( "fmt" ) func main() { var h Hello h = hello{} fmt.Println("Hello", h.World()) } type Hello interface { World() string } type hello struct {} func (h hello) World() string { // ここを値型にする return "world" }
- warning
- 後者の対応は(値渡しになるため)フィールドの編集ができなくなるので注意。
- 参考
宣言時にその型の初期値がゼロ値と同じなら省略すべき
- 警告
- should drop = 0 from declaration of var value; it is the zero value
- NG
var test int = 0
- OK
var test int
- ゼロ値
少なくとも以下の型のゼロ値は覚えておきましょう。
- string
""
- bool
false
- interface{}
nil
(errorもこれ)
- ポインタ
nil
上記以外の
int
やrune
等の数値型は0
がゼロ値です。
初期値から型が推測できるので、型の指定を省略すべき
- 警告
- should omit type int from declaration of var test; it will be inferred from the right-hand side
- NG
var num int = 1
- NG
var num = 1
- OK
num := 1
- OK
var num rune = 1
- info
- ちなみに
rune
などの型は値から推測できないので、指定すべきです。
- ちなみに
nil を返却することができない
- エラー
- ポインタやインターフェース型以外が返却値として指定された場合は、
nil
を返却することはできません。- cannot use nil as type SomeStruct in return argument
- ポインタやインターフェース型以外が返却値として指定された場合は、
- 対応
- 構造体の場合は値を指定せずに返却すれば、フィールドには各型のゼロ値が格納されます
- NG
type SomeStruct struct { Id integer Name string } func Function() SomeStruct { return nil }
- OK
type SomeStruct struct { Id integer Name string } func Function() SomeStruct { return SomeStruct{} }
==
の比較演算子で異なる型の値を比較した
- エラー
- 例えば、数値と nil を比較するとエラーになります。
- invalid operation: val == nil (mismatched types string and nil)
- 例えば、数値と nil を比較するとエラーになります。
- NG
var val int if val == nil { print(val) }
- OK
var val int if val == 0 { print(val) }
integer や string のようなプリミティブな変数は定義した時点で各型のゼロ値で初期化されます。
数値の場合は 0
、文字列の場合は ""(空文字)
がゼロ値です。
文字列の数値変換をint()で行った
文字列からの数値変換は strconv.Atoi
関数で行います。
- エラー
- int 関数では文字列を数値に変換することはできません
- cannot convert "123" (type untyped string) to type int
- 明示的な変換以外にも、チャネルと異なる型を送信して自動変換された場合にも同じエラーが発生することがあります
- int 関数では文字列を数値に変換することはできません
- NG
i := int("123")
- OK
i, _ := strconv.Atoi("123")
- NG
ch := make(chan int) ch <- "abc"
- OK
ch := make(chan int) ch <- 1000
宣言済みの変数に異なる型の値を代入しようとした
- エラー
- 変数の型と異なる値を代入することはできません
- cannot use "abc" (type string) as type int in assignment
- 変数の型と異なる値を代入することはできません
- 対応
- 変数の型を合わせましょう。
- NG
var i int i = "abc"
- OK
var i string i = "abc"
- OK
var i int i = 123
ポインタ型でない変数に ポインタとしてアクセスした
- エラー
- アドレスで指定されるべき引数に
*
をつけてアクセスするとエラーになります。- invalid operation: cannot indirect a (variable of type int)
- invalid indirect of a (type int)
- アドレスで指定されるべき引数に
- 対応
- 変数をポインタとして渡してあげる場合は
&
をつけてアドレスを取得しましょう。
- 変数をポインタとして渡してあげる場合は
- NG
a := 1 fmt.Println(*a)
- OK
b := 1 a := &b fmt.Println(*a)
- OK
a := &[]int{1, 2} fmt.Println(*a)
構造体を引数とする場合は省メモリの観点からポインタ型で受け取ることが多いので、 最後の例のように初期化と同時にアドレスを取得するような書き方もできます。
パッケージ関連
循環インポートは許可されていない
- エラー
- Go ではパッケージ同士が参照し合うようなインポートは許可されていません。
- import cycle not allowed
- Go ではパッケージ同士が参照し合うようなインポートは許可されていません。
- 対応
- 参照方向が一方向になるように移動したり、同一パッケージ内に入れて参照するなどの対応が考えられます。
- NG
a
packageb
package
- OK
a
packageb
package
インポート対象のパスが不正
- エラー
- インポートするパスがスラッシュで終わっているとエラーになります
- non-canonical import path "note.crohaco.net/packagename/" (should be "note.crohaco.net/packagename")
- インポートするパスがスラッシュで終わっているとエラーになります
- NG
import "note.crohaco.net/packagename/"
- OK
import "note.crohaco.net/packagename"
パッケージパスの先頭にドット(.
)が含まれていない
- エラー
- インポートに指定したパスの先頭にドットが含まれていない(ドメインでない)というエラーです。
- imports hello/world: malformed module path "hello/world": missing dot in first path element
- インポートに指定したパスの先頭にドットが含まれていない(ドメインでない)というエラーです。
- NG
- (GOPATHモードの状態で)
import "hello/world"
- (GOPATHモードの状態で)
- OK
import "hello.com/world"
- OK
- (
go.mod
にmodule hello
が指定されている状態で)import "hello/world"
- (
- info
- ただし、 モジュールモード
が有効な場合、
go.mod
で指定したモジュール名と一致していればエラーにはなりません。 - 逆に言えばモジュールモードが有効でこのエラーが出る場合、 go.modのモジュール名と一致していないことが考えられます。
- ただし、 モジュールモード
が有効な場合、
package 文にダブルクォートを指定した
- エラー
- package の指定にダブルクォートは必要ありません。
- expected 'IDENT', found "main"
- package の指定にダブルクォートは必要ありません。
- NG
package "main"
- OK
package main
インポートしたパッケージが存在しない
- エラー
- 当然ですが存在しないパッケージはインポートできません
- cannot find package "aaaaa" in any of:
- 当然ですが存在しないパッケージはインポートできません
- 対応
- ローカルからインポートする場合は、カレントディレクトリからのパス
(
./
) を記述しましょう。
- ローカルからインポートする場合は、カレントディレクトリからのパス
(
- NG
import "invalidPackage"
- OK
import "validPackage"
- OK
import "./local/path/to/package"
package文が書かれていない
- エラー
- Goのファイルは必ず一つのパッケージに属するためpackage文がないとエラーになります
- expected 'package', found 'EOF'
- expected 'package', found 'import'
- Goのファイルは必ず一つのパッケージに属するためpackage文がないとエラーになります
- NG
import "fmt"
- OK
package main import "fmt"
import文に文字列以外が指定されている
- エラー
- import文に文字列が指定されていないとエラーになります
- expected 'STRING', found newline
- import文に文字列が指定されていないとエラーになります
- NG
import fmt
- OK
import "fmt"
main以外のパッケージは実行できない
- エラー
go run test.go
のようにファイルを実行するとき、 test.go が main パッケージに属していなければエラーになります。- cannot run non-main package
- package test; expected main
- NG
package test
- OK
package main
- info
- また処理の起点となる
main
存在しない場合もエラーになります。- runtime.main_main·f: function main is undeclared in the main package
- また処理の起点となる
同じディレクトリ内に異なるパッケージに属したファイルが存在する
- エラー
- Golang のインポートはディレクトリ単位で行われます。
そのため、同一ディレクトリ内に異なるパッケージに属するファイルが存在するとエラーになります。
- found packages test1 (test1.go) and test2 (test2.go) in /path/to/test
- Golang のインポートはディレクトリ単位で行われます。
そのため、同一ディレクトリ内に異なるパッケージに属するファイルが存在するとエラーになります。
- NG
- test/test1.go
- test/test2.go
package test1
package test2
- OK
- test/test1.go
- test/test2.go
package test
package test
- info
- パッケージ名は統一さえされていれば、ディレクトリ名と一致していなくても構いません
同じ名前のパッケージを再インポートした
- エラー
- 同じ名前のパッケージを再度インポートするとエラーになります
- test redeclared as imported package name
- 同じ名前のパッケージを再度インポートするとエラーになります
- 再現
同じパッケージ名を持つディレクトリがあると: 例えばこのように同じパッケージ名をもつ異なるディレクトリがあるとき
- test1/test.go
- test2/test.go
package test func Test() { println("test1") }
package test func Test() { println("test2") }
両方を普通にインポートするとエラーとなります
- 対応
- 別名を付けてインポートしてあげましょう。
- NG
import ( "./test1" "./test2" )
- OK
import ( "./test1" test2 "./test2" )
ゴルーチン関連
go文で関数を呼び出していない
- エラー
- go文に呼び出されていない関数を指定すると上記のエラーが発生します。
- function must be invoked in go statement
- go文に呼び出されていない関数を指定すると上記のエラーが発生します。
- NG
go func() {}
- OK
go func() {}()
チャネルの型と違う値を送信しようとした
- エラー
- チャネルの型と違う値を送信することはできません
- cannot use i (type string) as type int in send
- チャネルの型と違う値を送信することはできません
- NG
ch := make(chan int) ch <- "abc"
- OK
ch := make(chan int) ch <- 1000
チャネルから送信したデータを受け取るべき goroutine が存在しない
- (多分)パニック
- チャネルからデータを送信するとき、送信側の処理がブロックされ続けてしまうのを防止するランタイムエラーのようです。
- all goroutines are asleep - deadlock!
- チャネルからデータを送信するとき、送信側の処理がブロックされ続けてしまうのを防止するランタイムエラーのようです。
- 再現
以下のようなチャネルとチャネルを引数に取るデータ受け取り用の関数があるとします。
var ch chan int = make(chan int) func receive(ch <-chan int) { fmt.Println(<-ch) fmt.Println("received") }
この関数がチャネルから送信したデータを受け取ってくれないと送信元はいつまで経っても処理を再開できません。 つまり、 receive 関数がゴルーチンとしてデータを待ち受けているかどうかがエラー発生を左右します。
- NG
func main() { ch <- 123 }
- OK
func main() { go receive(ch) ch <- 123 }
- info
- ただし、チャネルからデータを受け取るかどうかに関わらず 一つ以上動作しているゴルーチンがあるとこのランタイムエラーは発生しません。
その他
分類できなかった子達です
参照しようとした変数等が定義されていない
- エラー
- 参照しようとしている変数やパッケージ定義されていないとエラーが発生します
- undefined: value
- undefined: fmt
- 参照しようとしている変数やパッケージ定義されていないとエラーが発生します
- 対応
- 「定義されていないから代入文で宣言しようとしたら発生した」というケースも多いでしょう。
=
を使った代入は既存変数への代入を意味します。- ローカル変数の宣言は
:=
を使いましょう。
- NG
value = 1
- OK
value := 1
- info
- 定義しているつもりでも 参照されるスコープから外れている場合、 このエラーが発生することがあります。
- NG
if test == 1 { value := 1 } print(value) // undefined: value
- NG
if value, ok := dict[key]; !ok { // この書き方だと value は if 文の中でのみ有効 value = 1 } print(value) // undefined: value
- OK
value, ok := dict[key] if !ok { value = 1 } print(value)
if文に等値条件ではなく代入文を指定した
- エラー
- 主にタイポで
==
ではなく=
を使って比較するとこうなります- syntax error: assignment a = 0 used as value
- expected boolean expression, found assignment (missing parentheses around composite literal?)
- syntax error: assignment a = 0 used as value
- 主にタイポで
- NG
if a = 1 { }
- OK
if a == 1 { }
- info
- Golangの if文は条件に真偽値のみを指定できます。 また、代入文も値を返却しないのでこのような不正な構文があるとエラーになります。
プログラムの構文として不正な文字列が含まれている
- エラー
- これはGoに限った話ではないんですが、プログラムの制御に関係ない文字が入っていると構文エラーになります
- invalid character U+0008
- これはGoに限った話ではないんですが、プログラムの制御に関係ない文字が入っていると構文エラーになります
- info
- Mac の場合
0x08
という不可視の制御文字が入力されてしまうことがあります。(Slackとかでも問題になりましたね.. - Macを使う場合はエディタの設定などで乗り切りましょう。もしくはOSを変えるなど。
- Mac の場合
- 参考
定数に再代入しようとした
- エラー
- const で定義した定数に対して再び値を割り当てようとするとエラーになります。
- cannot assign to val
- const で定義した定数に対して再び値を割り当てようとするとエラーになります。
- 対応
- 再代入が予想される場合は var で変数を定義しましょう。
- NG
const val = 1 func Function () { val = 2 }
- OK
var val = 1 func Function () { val = 2 }
:=
の左辺に定義済みの変数が指定されている
- エラー
:=
の左側に新しい変数が定義されていないとエラーになります。- no new variables on left side of :=
- 対応
- 既存変数への代入は
=
で行うようにしましょう。 value, err := f()
のように多値が返却される場合、value
かerr
のいずれか片方が新規の変数である必要があります。
- 既存変数への代入は
- NG
value := Function() value := Function2()
- OK
value := Function() value = Function2()
- NG
value, err := Function() value, err := Function2()
- OK
value, err := Function() value2, err := Function2()
- info
_
(ブランク識別子)のみ値を代入しようとすると同じエラーが発生するようですfunc Function() { _ := 1 }
_
変数に代入された値は使用できない
- エラー
- cannot use _ as value
- NG
value, _ := Function() print(_)
- OK
value, test := Function() print(test)
使われていないローカル変数やパッケージがある
- エラー
- value declared and not used
- imported but not used ...
- value declared and not used
- 対応
- 使わない変数は
_
(ブランク識別子)に代入しましょう。
- 使わない変数は
- NG
value, err := Function()
- OK
value, _ := Function()
- OK
import _ "./statik"
- info
- 最後の例は blank import というらしいです。
- 実行はされてほしいけどそのファイル内でパッケージが使われない場合に使います。
- 参考
- info
- 評価結果が使われない場合もエラーになります。
1 == 1 evaluated but not used
- 普通こんなことはしませんが、宣言部分だけを削除すると 比較部分だけが取り残されてこのようなエラーが発現することがあります。
関数や構造体の定義が複数行にまたがる場合、行末がカンマか括弧で終わっていない
- エラー
- 構造体の初期化や関数の引数指定で各要素を改行で区切るとき、最終要素が改行で終わっているとこのエラーが発生します。
- syntax error: unexpected newline, expecting comma or )
- syntax error: unexpected newline, expecting comma or }
- missing ',' before newline in composite literal
- 構造体の初期化や関数の引数指定で各要素を改行で区切るとき、最終要素が改行で終わっているとこのエラーが発生します。
- 対応
- カンマを追加するか、行末を括弧で終わらせるようにします。
- NG
arr := [] int { 1, 2 }
- NG
arr := [] int { 1, 2, }
- OK
arr := [] int { 1, 2}
- OK
test( 1, 2 )
- OK
test( 1, 2, )
- OK
test( 1, 2)
- info
- カンマ以外にも
+
等の中置き演算子が行末にある場合は継続行と判断されるようです
- カンマ以外にも
- 参考
ポインタ型変数にnilが入っている状態で参照しようとした
- パニック
- runtime error: invalid memory address or nil pointer dereference
- NG
var a *int fmt.Println(*a)
- NG
var a *int *a = 1
- OK
var a *int b := 1 a = &b // 以下のように値のアドレスを直接参照することはできない a = &1 // cannot take the address of 1 (untyped int constant) a = &nil // cannot take address of nil (untyped nil value)
- OK
var b *int = nil // 同じポインタ型はそのまま格納できる a = b // ポインタ型の変数のアドレスは型が異なるため格納できない a = &b // cannot use &b (value of type **int) as *int value in assignment
スライスののインデックスに負値を指定した
- エラー
- Pythonのようにスライスの後ろの方から要素を取得するときにマイナスのインデックスを使うことはできません。
- invalid slice index -1 (index must be non-negative)
- Pythonのようにスライスの後ろの方から要素を取得するときにマイナスのインデックスを使うことはできません。
- 対応
- どうしても後ろからのインデックスを指定する場合には スライスの要素数からマイナスして要素のインデックスを求めましょう。
- NG
a := []int{1, 2, 3} fmt.Println(a[-1])
- OK
a := []int{1, 2, 3} fmt.Println(len(a)-1)
スライスの要素数以上のインデックスを参照した
- パニック
- 要素数以上のインデックスを指定して要素を取得しようとするとパニックが発生します。
- runtime error: index out of range [3] with length 3
- 要素数以上のインデックスを指定して要素を取得しようとするとパニックが発生します。
- 対応
- 要素数未満のインデックスを指定するか、固定のインデックスを指定するときは要素数のチェックをしましょう。
- NG
a := []int{1, 2, 3} fmt.Println(a[3])
- OK
a := []int{1, 2, 3} fmt.Println(a[2])
range文で得られる2番めの値が使われていないので省略するべき
- 警告
- should omit 2nd value from range; this loop is equivalent to
for serial := range
- should omit 2nd value from range; this loop is equivalent to
- NG
for index, _ := range values { }
- OK
for index := range values { }