前提・実現したいこと
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/* 2 略 3*/ 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/* 2 略 3*/ 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}
range は各要素のコピーを返すので、要素を更新したいのであれば index を使って処理する必要があります。
https://inabajunmr.hatenablog.com/entry/2019/11/07/093217
ありがとうございます。
「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])
}
```
回答の部分に投稿していただけるとベストアンサーにして解決済みにできるですが、、
お手数ですがお願いできますか?
回答1件
あなたの回答
tips
プレビュー