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

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

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

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

Q&A

解決済

1回答

1126閲覧

[Go]UserとTweetが1対多の関係でTweetにUserを追加する

kyo._.

総合スコア3

Go

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

0グッド

0クリップ

投稿2021/07/29 04:37

編集2021/07/29 04:54

前提・実現したいこと

GoでTwitterのようなアプリを作ろうとしています。
UserとTweetが1対多の関係です。

Tweetの一覧ページでTweetにUserの情報を追加しようとした際に、うまくできず詰まってしまいました。

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

ソースコードは以下の通りです。

models/tweet.go

go

1package models 2 3type Tweet struct { 4 ID int 5 Content string 6 UserID int 7 User User 8 CreatedAt time.Time 9} 10 11func GetTweets() (tweets []Tweet, err error) { 12 cmd := `select * from tweets` 13 rows, err := db.Db.Query(cmd) 14 if err != nil { 15 log.Fatalln(err) 16 } 17 for rows.Next() { 18 var t Tweet 19 err = rows.Scan(&t.ID, 20 &t.Content, 21 &t.UserID, 22 &t.CreatedAt) 23 if err != nil { 24 log.Fatalln(err) 25 } 26 tweets = append(tweets, t) 27 } 28 rows.Close() 29 30 return tweets, err 31}

models/user.go

go

1package models 2 3type User struct { 4 ID int 5 UUID string 6 Name string 7 Email string 8 PassWord string 9 CreatedAt time.Time 10 Tweets []Tweet 11} 12 13func GetUser(id int) (u User, err error) { 14 u = User{} 15 cmd := `select * from users where id = ?` 16 err = db.Db.QueryRow(cmd, id).Scan( 17 &u.ID, 18 &u.UUID, 19 &u.Name, 20 &u.Email, 21 &u.PassWord, 22 &u.CreatedAt, 23 ) 24 return u, err 25}

controllers/tweets_controller.go

go

1package controllers 2 3func TweetIndex(w http.ResponseWriter, r *http.Request) { 4 tweets, _ := models.GetTweets() 5 t := models.Tweet{} 6 for _, t = range tweets { 7 t.User, err = models.GetUser(t.UserID) 8 if err != nil { 9 fmt.Println(err) 10 } 11 fmt.Println(t) //①for文の中 12 } 13 fmt.Println(tweets) //②for文の外 14 generateHTML(w, tweets, "layout", "common/navbar_priv", "tweets/index") 15}

①for文の中では、
Tweetの持つUserがきちんと取得できたのですが、

②for文の外では、
Tweetの持つUserが初期値になってしまいます。

どのようにすれば、Tweetストラクトの持つUserにデータを反映できるのかがわかりません。

補足情報

ひとつひとつのTweetを表示するページでは、以下のようにすることでviewから呼び出せました。

models/tweet.go

go

1/* 23*/ 4 5func GetTweet(id int) (t Tweet, err error) { 6 cmd := `select * from tweets where id = ?` 7 t = Tweet{} 8 9 err = db.Db.QueryRow(cmd, id).Scan( 10 &t.ID, 11 &t.Content, 12 &t.UserID, 13 &t.CreatedAt) 14 return t, err 15}

controllers/tweets_controller.go

go

1/* 23*/ 4 5func TweetShow(w http.ResponseWriter, r *http.Request, id int) { 6 t, err := models.GetTweet(id) 7 if err != nil { 8 log.Println(err) 9 } 10 t.User, err = models.GetUser(t.UserID) 11 if err != nil { 12 fmt.Println(err) 13 } 14 generateHTML(w, t, "layout", "common/navbar_priv", "tweets/show") 15}

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

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

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

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

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

kyo._.

2021/07/29 06:18

ありがとうございます。 「range は各要素のコピーを返す」からできていなかったんですね。納得しました。 for文の部分を以下のようにするとできました。 ```go for i := 0; i < len(tweets); i++ { tweets[i].User, err = models.GetUser(tweets[i].UserID) if err != nil { fmt.Println(err) } fmt.Println(tweets[i]) } ```
kyo._.

2021/07/29 06:26

回答の部分に投稿していただけるとベストアンサーにして解決済みにできるですが、、 お手数ですがお願いできますか?
guest

回答1

0

ベストアンサー

range は各要素のコピーを返すので、要素を更新したいのであれば index を使って処理する必要があります。
参考: sliceをrangeでループして取得した値のフィールドを更新しても、元のsliceは更新されない(rangeで取得した値はコピー) - チョキチョキかにさん

go

1 for i := range tweets { 2 tweets[i].User, err = models.GetUser(tweets[i].UserID) 3 // 略 4 }

投稿2021/07/29 06:33

hoshi-takanori

総合スコア7901

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

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

kyo._.

2021/07/29 06:35

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問