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

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

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

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

Q&A

解決済

1回答

1411閲覧

【Go/gin】グローバル変数の値が次のリクエストにも引き継がれてしまう

n_kitamura

総合スコア17

Go

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

0グッド

0クリップ

投稿2017/04/27 02:41

例えば、以下のソースを実行してみると、一回目のリクエスト時は1、二回目以降のリクエストでは、2,3,4と増えていってしまいます。

go

1package controller 2 3import ( 4 "github.com/gin-gonic/gin" 5) 6 7var count = 0 8 9func Count(c *gin.Context) { 10 count += 1 11 c.JSON(200, count) 12} 13 14// main.goではhttpリクエストがあった際に上記の「Count」が実行されます。

以下のように呼び出される関数内で初期値を明示してあげると改善(常に1が出力される)しました。

func Count(c *gin.Context) { count = 0 count += 1 c.JSON(200, count) }

ずっとPHPをやっていた身としては中々衝撃的な動きに思うのですが、上記のように明示的に初期値を設定するのが普通なのでしょうか?

(似た問題としては、リクエスト時に作成したmysqlコネクションを明示的にcloseしてあげないと、リクエストのたびにmysqlコネクションが落ちずに残ってしまい「too many connection~」となってしまいました。)

よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

php

1<?php 2// Here your code ! 3$s1 = 0; 4 5function b(){ 6 $s1 += 1; // [sintax error] 7 return $s1; 8} 9echo b(); 10echo b(); 11?>

PHPには詳しくないですが、こうすると$s1の部分で変数が宣言されてないというエラーが起きますよね。
なのでPHPとgolangで同じ書き方をしてそれぞれ動作が違う、という感じではないんでしょうか。

golangでは関数の外側に書いた変数や関数のスコープは同一パッケージ内になります。
https://play.golang.org/p/P0vxDRYD1h
関数と変数のアクセス範囲に差がありません。
ファーストオブジェクトである(関数を変数として扱える)ことを除けば、これはC言語のグローバル変数と同様です。(たぶん)


golang明示的にcloseするのはMySQLのコネクションだけじゃなくて、http.Response.Bodyやファイルなどもです。
変数を取得した時点で

go

1res, err := http.Get("http://google.co.jp") 2if err != nil{ 3 log.Fatal(err) 4} 5defer res.Body.Close()

このように閉じる癖をつけましょう。
deferをつけると関数をぬけ出す時に呼ばれ(遅延実行)、プログラムが強制終了(panic等)した時にも呼ばれるようになります。


初学者の勉強用に素晴らしいサイトがあるので有効活用しましょう。
A Tour of Go

投稿2017/05/01 13:15

intelf___

総合スコア868

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

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

n_kitamura

2017/05/06 11:28

ご回答ありがとうございます! Goのスコープについてはこれから慣れていきたいと思います。 ただ、 >> ずっとPHPをやっていた身としては中々衝撃的な動きに思うのですが、 と思ったのはスコープについてではなく、 変数の状態が次のhttpリクエストに引き継がれてしまうというところです。 (PHPだと、セッション変数などを除いた普通の変数は、リクエストのたびにリセットされるので) どういう条件で変数の値が引き継がれてしまうのか理解して、毎回明示的にリセットしなければいけないと思うのですが、それがGoだと普通なのでしょうか? という質問でした。分かりづらかったようですみません。。 そして質問しておきながらお返事遅れて申し訳ありません。
n_kitamura

2017/05/06 13:38

うーん…。 セッション変数の話をしたかったわけではなく…。 PHPだと変数に格納された値が別のHTTPリクエストに引き継がれることがありません。 Go言語の場合(ginの場合?)だと、質問に書いたコードのように、Aさんがアクセスすると1が表示され、Bさんがアクセスすると2に、、となってしまう場合があります。 つまり、Aさんのアクセス時の変数の値がBさんのアクセス時に引き継がれてしまう。 そうなってしまう状況があるというのは、Go的には普通なんですかね?という質問です。
intelf___

2017/05/06 13:49 編集

普通ですね。 > golangでは標準のnet/httpではセッションの管理に対応していない ここで回答した気になっていました... セッションの管理がされないので、初期化もされません。 セッション変数などがないので、グローバル変数は常に引き継がれます。
n_kitamura

2017/05/06 13:50

そういうことでしたか。すみません。 結構衝撃です。 何度もご回答いただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問