質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

2198閲覧

Go言語のshort variable declarationの挙動が分かりません。

12000en

総合スコア7

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2017/09/09 18:38

Go言語の:=は変数宣言の短い書き方だと思っていたのですが、以下のコードのように変数errが二度:=で初期化されてるにも関わらずエラーが起きない理由を教えてください。

go

1res, err := http.Get("http://example.com") 2if err != nil { 3 // 4} 5body, err := ioutil.ReadAll(res.Body) 6if err != nil { 7 // 8}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

https://golang.org/ref/spec#Short_variable_declarations

Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new.

通常の変数宣言とは異なり、短い変数宣言では同じブロックで以前に宣言された変数(ブロックが関数本体の場合はパラメータリスト)と同じ型の変数と、空白以外の変数の、少なくとも1つを新しく追加される変数として再宣言できます。

同じ型であれば、前に宣言された変数は再宣言される事なく利用され、新しく追加された物のみが宣言されます。ですので以下は型が異なる err ですのでコンパイルエラーになります。

go

1package main 2 3import ( 4 "errors" 5 "fmt" 6) 7 8func foo1() (int, error) { 9 return 0, nil 10} 11 12func foo2() (int, string) { 13 return 0, "foo" 14} 15 16func main() { 17 v1, err := foo1() 18 fmt.Println(v1, err) 19 20 v2, err := foo2() 21 fmt.Println(v2, err) 22}

https://play.golang.org/p/BvO1b_mZRx

また err が再利用されているかどうかは、以下で確認出来ます。

go

1package main 2 3import ( 4 "errors" 5 "fmt" 6) 7 8func foo1() (int, error) { 9 return 0, nil 10} 11 12func foo2() (int, error) { 13 return 0, errors.New("foo2") 14} 15 16func main() { 17 v1, err := foo1() 18 fmt.Println(v1, err) 19 p := &err 20 21 v2, err := foo2() 22 fmt.Println(v2, err) 23 24 fmt.Println(*p) 25}

https://play.golang.org/p/_hMC3oDPn0

最初の err をポインタ p で預けておき、foo2 の呼び出し後にデリファレンスしています。新しい変数が宣言されているならば、*p は nil になりますが、仕様通り変数が再利用されています。

投稿2017/09/11 02:58

mattn

総合スコア5030

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

12000en

2017/09/11 06:37

詳しい解説ありがとうございます!疑問が解消しました!
mattn

2017/09/11 09:38

ちなみに余談ですが、上書きされると defer が怖い様に感じるかもしれません。 defer はその時点の引数をキャプチャするので https://play.golang.org/p/00whwEYcy2 この様に呼び出しても、上書きされた err の値では showError は呼び出されません。なので安心して上書きされる変数を defer してもらって良いと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問