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

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

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

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

Q&A

解決済

1回答

840閲覧

Goの無名関数内で使用する変数がnil pointerになる

Shika_Tech

総合スコア13

Go

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

0グッド

0クリップ

投稿2022/05/02 05:47

前提

golang 1.18

実現したいこと

無名関数を変数に代入し、特定のエラーの時のみ再実行したい。

発生している問題・エラーメッセージ

再実行した時に、無名関数内で使用している変数の値がnil pointerになります。

該当のソースコード

go

1 2func (us *Interactor) CreateTrs(ctx context.Context, trs *transaction.Transaction) (*transaction.Transaction, apperror.AppError) { 3 var err apperror.AppError 4 5 // begin db transaction 6 f := func() apperror.AppError { 7 err := us.tx.WithTx(ctx, func(ctx context.Context) apperror.AppError { 8 fmt.Println("-------------------------") 9 fmt.Println(trs) 10 fmt.Println("-------------------------") 11 if err = us.transactionService.ConfirmNotExceedAmountLimit(ctx, trs.UserID, trs.Amount); err != nil { 12 return err 13 } 14 15 trs, err = us.transactionRepository.Save(ctx, trs) 16 if err != nil { 17 return err 18 } 19 20 return nil 21 }) 22 return err 23 } 24 err = f() 25 if errors.Is(特定のエラー)) { 26 err = f() 27 } 28 if err != nil { 29 return nil, err 30 } 31 32 return trs, nil 33} 34

errors.Isがtrueになった場合 f()が再試行されるとこまではいいのですが、 trsがnilになり nil pointerになってしまいます。

go

1fmt.Println("-------------------------") 2fmt.Println(trs) 3fmt.Println("-------------------------") 4 5// output 6------------------------- 7<nil> 8------------------------- 9

試したこと

無名関数の代入前にnilになる変数をコピーすれば nilにならない事を確認しました。

go

1 2ttt := trs 3f := func() apperror.AppError { 4// tttを使う 5 6

上記で一応エラーは回避できたのですが、これが良い方法なのか、中で何が起こっているのかがわかっておりません。
知見がございましたらアドバイス頂けると幸いです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

見慣れない書き方かつ未知のライブラリを参照しているので把握しきれていないですが、
疑似コードを書いてみるとちゃんとnilにならずに動作しました。

https://go.dev/play/p/xe0Pvj3PvbE

おそらくリトライ時「us.transactionRepository.Save」でエラーが出ていないでしょうか?
(つまりerrがnot-nilでtrsにnilが代入されている?)

無名関数の外側の変数を参照するだけならいいのですが、
無名関数の外側の変数を上書きするのは挙動が読みにくくなるのでお勧めしません。
(あまり使いまわすメリットもないと思います)

投稿2022/05/03 13:18

nobonobo

総合スコア3367

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

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

Shika_Tech

2022/05/03 14:03

playgroundまで作って頂きありがとうございます。 実際には以下のようなコードに近いです。 https://go.dev/play/p/nWJHg6XDO4k > おそらくリトライ時「us.transactionRepository.Save」でエラーが出ていないでしょうか? (つまりerrがnot-nilでtrsにnilが代入されている?) まさにその通りで Saveでerrが返り trs がnilとなっている場合に リトライ処理をすると trs.UserID などで trsのフィールドを見る時に nil pointer になっておりました。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問