続「Goプログラミング実践入門」の写経がとてもいい勉強になった

サンプルソースを写経していて、どーしても気になるところがあったのでメモしておきます。
blog.suganoo.net

(※2018/12/06更新 全然ちがうところ修正していたので更新)

開始ユーザーが表示されない

f:id:suganoo:20181206103538p:plain

User.Nameって無いよね

ここの部分の .User.Name が無いせいで、スレッドを表示させる時に開始ユーザーが表示されません。
gowebprog/index.html at 46faa1da9ae329950ec5f94d903a3165646e9085 · mushahiroyuki/gowebprog · GitHub

      開始ユーザー {{ .User.Name }} - 開始日 {{ .CreatedAtDate }} - 投稿数 {{ .NumReplies }}。

上のリンクは翻訳者のかたのリンクなのですが著者の方にもありません。

UserとThreadはバインディングされていません

というのもUserの結果ってバインディングされてないように見えます。
gowebprog/user.go at 46faa1da9ae329950ec5f94d903a3165646e9085 · mushahiroyuki/gowebprog · GitHub

type User struct {
	Id        int
	Uuid      string
	Name      string
	Email     string
	Password  string
	CreatedAt time.Time
}

type Thread struct {
	Id        int
	Uuid      string
	Topic     string
	UserId    int       // <--- 単純に UserId だけでUserとはバインディングされていない
	CreatedAt time.Time
}

なのでサンプルをそのまま使っても、そりゃ表示されないです。

俺なりに修正してみた

自分なりにFolkして修正してみました。今日は疲れてしまったのでしっかり動作確認してないし、眠いので動かなかったらご勘弁。
なのでプルリクも出すつもりもありません。参考までにしてください。

修正箇所

全体修正箇所github.com

ThreadとUserについて

まずThreadについては下記のようにUser構造体を持つようにしました。
update UserofThread · suganoo/gowebprog@09b5348 · GitHub

type Thread struct {
	Id        int
	Uuid      string
	Topic     string
	UserOfThread  User    //<--- これ
	CreatedAt time.Time
}

そんでThreads()でThreadを取ってくる時に、ちゃんとidでUserのデータも取ってくるように修正。
ついでに UserById関数も作っておきました。
gowebprog/thread.go at 09b53482accc3750b04017ab4b6c0b33fcc62249 · suganoo/gowebprog · GitHub

func UserById(id string) (user User, err error) {
 	user = User{}
 	err = Db.QueryRow("SELECT id, uuid, name, email, password, created_at FROM users WHERE id = $1", id).
 		Scan(&user.Id, &user.Uuid, &user.Name, &user.Email, &user.Password, &user.CreatedAt)
 	return
 }

スレッドを取ってくるところ

	for rows.Next() {
		conv := Thread{}
		userId := ""
		if err = rows.Scan(&conv.Id, &conv.Uuid, &conv.Topic, &userId, &conv.CreatedAt); err != nil {
			return
		}
		user := User{}
		user, err := UserById(userId)
		if err != nil {
			return
		}
		conv.UserOfThread = user
		threads = append(threads, conv)
	}

表示側のindex.htmlも .UserOfThread.Nameで表示できるようになります。たぶん。
update UserofThread · suganoo/gowebprog@09b5348 · GitHub

開始ユーザー {{ .UserOfThread.Name }} - 開始日 {{ .CreatedAtDate }} - 投稿数 {{ .NumReplies }}。

こんな風にユーザー名が取れました。
f:id:suganoo:20181206103617p:plain
テストコードまで直す気力はも無いので寝ます。。。。

最後

サンプルコードは参考までに読むものですね。
著者の方も結構issue出てるのに、全然答える気配がないようです。もう興味が薄れてしまったんでしょうかね。

あと運用上気になった所として下記の2つのアクセスが頻繁になると思われます。

  • ページ遷移ごとにsessionをsessionsテーブルに確認しに行ってる
  • 上述のUserを取得するところでスレッドを全部取得する時に毎回Usersテーブルにアクセスしてる

おそらく運用上はkey value的なredisを使うとかした方がDBのアクセスを減らせるでしょう。