前提・実現したいこと
echoでのユーザー情報をUpdateする関数の実装
http://localhost:8888/api/v1/users/:id にてPUTでユーザーを更新しようとしています
{"name" : "なまえ"} という様なjsonを送ってとりあえず処理を実行したいと思ってます.
使用ツール
- echo
- gorm
発生している問題・エラーメッセージ
ルーティング・(送信している)JSON・dbのコネクションなどは,他のCRAETE・READ・DELETEが同じような処理で動いているのため問題ないと思います.
500: Internal Server Error
該当のソースコード
go
1func UpdateUser() echo.HandlerFunc { 2 return func(c echo.Context) (err error) { 3 db, err := gorm.Open("mysql", "mysql設定") 4 CheckConnectError(err) //エラーハンドリングの関数 5 defer db.Close() 6 7 user := new(model.User) 8 if err := c.Bind(user); err != nil { 9 return err 10 } 11 id, _ := strconv.Atoi(c.Param("id")) 12 model.Users[id].Name = user.Name 13 return c.JSON(http.StatusOK, "ok") 14 } 15}
model.Users[id].Nameは,modelパッケージのUsers変数をidで取ってきてNameに代入がしたくて書いています.
公式のドキュメントを参考にしました.
## model/user.go ~略 var ( Users = map[int]*User{} Seq = 1 ) 略~
https://echo.labstack.com/cookbook/crud
処理がおかしいところはありますでしょうか.
よろしくお願いします
追記
ログはこのようになっております.
log
1time:2019-07-26T15:37:53+09:00 host:::1 2forwardedfor: req:- 3status:500 4method:PUT 5uri:/api/v1/users/3 6size:36 referer: 7ua:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 8reqtime_ns:1895431 9cache:- runtime:- 10apptime:- 11vhost:localhost:8888 12reqtime_human:1.895431ms 13x-request-id: host:localhost:8888
下記はかなり見辛いログですが,載せておきます.
log
1{"time":"2019-07-26T15:37:53.480874+09:00","level":"-","prefix":"echo","file":"recover.go","line":"73","message":"[PANIC RECOVER] runtime error: invalid memory address or nil pointer dereference goroutine 50 [running]:\necho/middleware.RecoverWithConfig.func1.1.1(0x156b148, 0x1000, 0xc000060000, 0x160b140, 0xc0002b2120)\n\t/Users/kirohi/go/src/echo/middleware/recover.go:71 +0xf1\npanic(0x14cc0e0, 0x195b440)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/runtime/panic.go:522 +0x1b5\ngithub.com/ia17011/subsc/backend/api.UpdateUser.func1(0x160b140, 0xc0002b2120, 0x0, 0x0)\n\t/Users/kirohi/go/src/github.com/ia17011/subsc/backend/api/user.go:74 +0x19d\ngithub.com/labstack/echo.(*Echo).add.func1(0x160b140, 0xc0002b2120, 0xc0002160a0, 0xf)\n\t/Users/kirohi/go/src/github.com/labstack/echo/echo.go:505 +0x87\ngithub.com/ia17011/subsc/backend/api/middlewares.serverHeader.func1(0x160b140, 0xc0002b2120, 0x156b148, 0x1000)\n\t/Users/kirohi/go/src/github.com/ia17011/subsc/backend/api/middlewares/mainMiddlewares.go:25 +0x235\necho/middleware.RecoverWithConfig.func1.1(0x160b140, 0xc0002b2120, 0x0, 0x0)\n\t/Users/kirohi/go/src/echo/middleware/recover.go:78 +0xd5\necho/middleware.LoggerWithConfig.func2.1(0x160b140, 0xc0002b2120, 0x3, 0x4)\n\t/Users/kirohi/go/src/echo/middleware/logger.go:119 +0x1c0\ngithub.com/labstack/echo.(*Echo).ServeHTTP(0xc00028a000, 0x15fe860, 0xc0002bc000, 0xc0001e8a00)\n\t/Users/kirohi/go/src/github.com/labstack/echo/echo.go:616 +0x22d\nnet/http.serverHandler.ServeHTTP(0xc000226750, 0x15fe860, 0xc0002bc000, 0xc0001e8a00)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/http/server.go:2774 +0xa8\nnet/http.(*conn).serve(0xc00021e0a0, 0x15ff560, 0xc0001ecc00)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/http/server.go:1878 +0x851\ncreated by net/http.(*Server).Serve\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/http/server.go:2884 +0x2f4\n\ngoroutine 1 [IO wait]:\ninternal/poll.runtime_pollWait(0x1e91ea8, 0x72, 0x0)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/runtime/netpoll.go:182 +0x56\ninternal/poll.(*pollDesc).wait(0xc000232818, 0x72, 0x0, 0x0, 0x154be4a)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/internal/poll/fd_poll_runtime.go:87 +0x9b\ninternal/poll.(*pollDesc).waitRead(...)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/internal/poll/fd_poll_runtime.go:92\ninternal/poll.(*FD).Accept(0xc000232800, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/internal/poll/fd_unix.go:384 +0x1ba\nnet.(*netFD).accept(0xc000232800, 0x30, 0x50, 0x50)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/fd_unix.go:238 +0x42\nnet.(*TCPListener).accept(0xc0002222f8, 0xc0f05880cb, 0xc000088000, 0xc00010dd00)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/tcpsock_posix.go:139 +0x32\nnet.(*TCPListener).AcceptTCP(0xc0002222f8, 0x100000001, 0xc00010dd30, 0x104c368)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/tcpsock.go:247 +0x48\ngithub.com/labstack/echo.tcpKeepAliveListener.Accept(0xc0002222f8, 0xc00010dd58, 0x10afda6, 0x5d3a9fc1, 0x1036bcf)\n\t/Users/kirohi/go/src/github.com/labstack/echo/echo.go:820 +0x2f\nnet/http.(*Server).Serve(0xc000226750, 0x15fe4e0, 0xc000222300, 0x0, 0x0)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/net/http/server.go:2859 +0x22d\ngithub.com/labstack/echo.(*Echo).StartServer(0xc00028a000, 0xc000226750, 0x0, 0x0)\n\t/Users/kirohi/go/src/github.com/labstack/echo/echo.go:707 +0x388\ngithub.com/labstack/echo.(*Echo).Start(...)\n\t/Users/kirohi/go/src/github.com/labstack/echo/echo.go:627\nmain.main()\n\t/Users/kirohi/go/src/github.com/ia17011/subsc/backend/main.go:16 +0x67\n\ngoroutine 51 [runnable]:\ndatabase/sql.(*DB).connectionOpener(0xc0002ca000, 0x15ff560, 0xc000220300)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/database/sql/sql.go:1000 +0xe8\ncreated by database/sql.OpenDB\n\t/usr/local/Cellar/go/1.12.5/libexec/src/database/sql/sql.go:670 +0x15e\n\ngoroutine 35 [runnable]:\ngithub.com/go-sql-driver/mysql.(*mysqlConn).startWatcher.func1(0xc0001f9080, 0xc0002c6120, 0xc0001f62a0)\n\t/Users/kirohi/go/src/github.com/go-sql-driver/mysql/connection.go:619 +0xbf\ncreated by github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher\n\t/Users/kirohi/go/src/github.com/go-sql-driver/mysql/connection.go:616 +0xbe\n\ngoroutine 52 [runnable]:\ndatabase/sql.(*DB).connectionResetter(0xc0002ca000, 0x15ff560, 0xc000220300)\n\t/usr/local/Cellar/go/1.12.5/libexec/src/database/sql/sql.go:1013 +0x\n"}
api/user.goと送信しているjsonの追記
go
1package api 2 3import ( 4 "fmt" 5 "net/http" 6 "strconv" 7 8 "github.com/ia17011/subsc/backend/model" 9 "github.com/jinzhu/gorm" 10 "github.com/labstack/echo" 11 uuid "github.com/satori/go.uuid" 12) 13 14func getUUID() string { 15 u, err := uuid.NewV4() 16 if err != nil { 17 fmt.Printf("Something went wrong: %s", err) 18 } 19 uu := u.String() 20 return uu 21} 22 23func CreateUser() echo.HandlerFunc { 24 return func(c echo.Context) (err error) { 25 db, err := gorm.Open("mysql", "kirohi:cSbuS2mlGo##@/subsc?charset=utf8&parseTime=True&loc=Local") 26 CheckConnectError(err) 27 defer db.Close() 28 user := &model.User{ 29 Id: model.Seq, 30 } 31 if err := c.Bind(&user); err != nil { 32 return err 33 } 34 35 model.Users[user.Id] = user 36 model.Seq++ 37 db.Create(&user) 38 return c.JSON(http.StatusOK, user) 39 } 40} 41func FindUserById() echo.HandlerFunc { 42 return func(c echo.Context) (err error) { 43 db, err := gorm.Open("mysql", "kirohi:cSbuS2mlGo##@/subsc?charset=utf8&parseTime=True&loc=Local") 44 CheckConnectError(err) 45 defer db.Close() 46 user := model.User{} 47 48 id := c.Param("id") 49 db.First(&user, id) 50 51 return c.JSON(http.StatusOK, user) 52 } 53} 54 55func UpdateUser() echo.HandlerFunc { 56 return func(c echo.Context) (err error) { 57 db, err := gorm.Open("mysql", "kirohi:cSbuS2mlGo##@/subsc?charset=utf8&parseTime=True&loc=Local") 58 CheckConnectError(err) 59 defer db.Close() 60 61 user := model.User{} 62 if err = c.Bind(user); err != nil { 63 return 64 } 65 id, _ := strconv.Atoi(c.Param("id")) 66 db.Where("Id=?", id).Find(&user) 67 68 user.Name = c.Param("name") 69 70 fmt.Println(user.Name) 71 // //model.Users[id].Name = "あああ" 72 // //fmt.Println(model.Users[id]) 73 // return c.JSON(http.StatusOK, user) 74 return c.JSON(http.StatusOK, "ok") 75 } 76} 77 78func DeleteUser() echo.HandlerFunc { 79 return func(c echo.Context) (err error) { 80 db, err := gorm.Open("mysql", "kirohi:cSbuS2mlGo##@/subsc?charset=utf8&parseTime=True&loc=Local") 81 CheckConnectError(err) 82 defer db.Close() 83 user := model.User{} 84 85 name := c.Param("name") 86 87 db.Where("name=?", name).Find(&user) 88 db.Delete(&user) 89 90 return c.NoContent(http.StatusOK) 91 } 92} 93 94func NewUser(user *model.User) { 95 db, err := gorm.Open("mysql", "kirohi:cSbuS2mlGo##@/subsc?charset=utf8&parseTime=True&loc=Local") 96 CheckConnectError(err) 97 defer db.Close() 98 db.Create(user) 99} 100 101func FindUser(u *model.User) *model.User { 102 db, err := gorm.Open("mysql", "kirohi:cSbuS2mlGo##@/subsc?charset=utf8&parseTime=True&loc=Local") 103 CheckConnectError(err) 104 defer db.Close() 105 106 user := model.User{} 107 db.Where(u).First(&user) 108 return &user 109} 110
json
http://localhost:8888/api/v1/users/3 というurlに対して,{ "name" : "あああ" } というbodyをContent-Type application/json,POSTで投げています.
ここでidが3であるユーザーの存在は,FindByUserID(),すなわちGETリクエストで確認できています.