From 9d8796f9a23fffeba0429941eac88bbf3e87e7e2 Mon Sep 17 00:00:00 2001 From: sharin-sushi Date: Mon, 18 Dec 2023 06:04:32 +0900 Subject: [PATCH] =?UTF-8?q?=E5=AE=9F=E9=A8=93=E5=AE=8C=E4=BA=86=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test0015Go/cmd/main.go | 32 +++-- test0015Go/infra/db.go | 253 --------------------------------- test0015Go/sample/for_rang.go | 10 +- test0015Go/sample/type_json.go | 192 +++++++++++++++++++++++++ 4 files changed, 220 insertions(+), 267 deletions(-) create mode 100644 test0015Go/sample/type_json.go diff --git a/test0015Go/cmd/main.go b/test0015Go/cmd/main.go index 34dae68..673bab0 100644 --- a/test0015Go/cmd/main.go +++ b/test0015Go/cmd/main.go @@ -1,22 +1,36 @@ package main -import "github.com/sharin-sushi/0015docker/sample" +import ( + "github.com/gin-gonic/gin" + "github.com/sharin-sushi/0015docker/sample" +) + +// "github.com/sharin-sushi/0015docker/sample" // 消えないようにメモ func main() { // pointer.go // for x, y := range のテスト - // r := gin.Default() - // r.GET("/1", test1) - // r.GET("/2", test2) - // r.GET("/2a", test2a) - // r.GET("/3", test3) - // r.Run("localhost:8080") - + r := gin.Default() + rangeTest := r.Group("/range") + { + rangeTest.GET("/1", sample.Test1) + rangeTest.GET("/2", sample.Test2) + rangeTest.GET("/2a", sample.Test2a) + rangeTest.GET("/3", sample.Test3) + } // crypt.go AES化 // sample.AlterMainCrypt2() //元記事ほぼそのままのもの - sample.AlterMainCrypt() //自分用に改変したもの + // sample.AlterMainCrypt() //自分用に改変したもの // pointer.go // このままだとニルポエラーでpanicして落ちる // sample.AleterMainPointer() + + // type_json.go + typeTest := r.Group("/type") + { + typeTest.GET("/vt-slise", sample.AlterMainType) + } + r.Run("localhost:8080") + } diff --git a/test0015Go/infra/db.go b/test0015Go/infra/db.go index e3171e7..04206e9 100644 --- a/test0015Go/infra/db.go +++ b/test0015Go/infra/db.go @@ -79,256 +79,3 @@ func migration() { // domain.KaraokeList{}, domain.Movie{}, ) } - -// // 会員登録 -// func CalltoSignUpHandler(c *gin.Context) { -// h := Handler{DB: Db} -// h.SignUpHandler(c) -// } - -// func (h *Handler) SignUpHandler(c *gin.Context) { -// var user domain.Listener -// err := c.ShouldBind(&user) -// if err != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": "Invalid request body", -// }) -// return -// } -// fmt.Printf("bindしたuser = %v \n", user) - -// err = user.ValidateSignup() -// if err != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": err.Error(), -// }) -// return -// } - -// existingUser, _ := domain.FindUserByEmail(h.DB, user.Email) //メアドが未使用ならnil -// fmt.Printf("existingUser= %v \n", existingUser) -// // ↓既存アカがあった際に、処理停止してくれるけど、c.JSONとfmt.Printはしてくれない、、、。 -// if existingUser.ListenerId != 0 { -// c.JSON(http.StatusBadRequest, gin.H{ -// "error": err.Error(), -// "message": "the E-mail address already in use", -// }) -// return -// } - -// //passwordの照合 -// user.Password = crypto.EncryptPasswordWithoutBackErr(user.Password) - -// result := Db.Select("listener_name", "email", "password").Create(&user) -// if result.Error != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": result.Error, -// }) -// return -// } - -// // IdをJWT化しCookieにセット -// trigerSetCookiebyUserAuth(c, user.ListenerId) - -// c.JSON(http.StatusOK, gin.H{ -// // "memberId": newMember.ListenerId, -// // "memberName": newMember.ListenerName, -// "message": "Successfully created user, and logined", -// }) -// } - -// //ログイン -// func CalltoLogInHandler(c *gin.Context) { -// h := Handler{DB: Db} -// h.LoginHandler(c) -// } -// func (h *Handler) LoginHandler(c *gin.Context) { -// var loginInput domain.Listener -// if err := c.ShouldBind(&loginInput); err != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "error": err.Error(), -// "message": "Invalid request body", -// }) -// return -// } - -// user, err := domain.FindUserByEmail(h.DB, loginInput.Email) //メアドが未登録なら err = !nil -// if err != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "error": err.Error(), -// "message": "the E-mail address id NOTalready in use", -// }) -// return -// } - -// CheckPassErr := crypto.CompareHashAndPassword(user.Password, loginInput.Password) //pass認証 -// if CheckPassErr != nil { -// c.JSON(http.StatusUnauthorized, gin.H{ -// "message": "Password is invalid", -// }) -// return -// } -// fmt.Printf("ChechkPassErr=%v \n", CheckPassErr) - -// // IdをJWT化しCookieにセット -// trigerSetCookiebyUserAuth(c, user.ListenerId) - -// c.JSON(http.StatusOK, gin.H{ -// "message": "Successfully Logged In", -// "listenerId": user.ListenerId, -// "listenerName": user.ListenerName, -// }) -// } - -// // IdをJWT化しCookieにセット。ログイン、サインイン時に呼び出される。 -// func trigerSetCookiebyUserAuth(c *gin.Context, ListenerId int) { -// // Token発行 = JWTでいいのかな? -// token, err := token.GenerateToken(ListenerId) -// if err != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": "Failed to sign up", -// }) -// return -// } -// // Cookieにトークンをセット -// cookieMaxAge := 60 * 60 * 24 * 365 - -// // domain := getdomain() -// domain := "localhost" - -// newCookie := &http.Cookie{ -// Name: "auth-token", -// // Name: "next-auth.session-token", -// Value: token, -// Path: "/", -// Domain: domain, -// MaxAge: cookieMaxAge, -// HttpOnly: true, -// Secure: true, //httpsの環境ではtrueにすること。 -// SameSite: http.SameSiteStrictMode, -// } -// http.SetCookie(c.Writer, newCookie) -// fmt.Printf("発行したcookie= %v /n", newCookie) -// } - -// func getdomain() string { -// // ローカル環境 -// if os.Getenv("ENV") == "local" { -// return "localhoset" -// // 本番環境 -// } else if os.Getenv("ENV") == "production" { -// return "my_domain" -// } else { -// return "" -// } -// } - -// // JWTからlistenerIdを取得。なお、コードの理解度低い。 -// func TakeListenerIdFromJWT(c *gin.Context) (int, error) { -// tokenString, _ := c.Cookie("auth-token") -// // tokenString, _ := c.Cookie("next-auth.session-token") 不要 - -// // token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { -// token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { -// return []byte(os.Getenv("SECRET_KEY")), nil -// }) -// if err != nil { -// c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"}) -// return 0, err -// } -// fmt.Printf("token= %v \n", token) - -// var listenerId int -// if claims, ok := token.Claims.(jwt.MapClaims); ok { -// if val, exists := claims["listener_id"]; exists { -// // JSON numbers are float64 - -// listenerIdFloat, ok := val.(float64) -// if !ok { -// // c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid listener_id format in token"}) -// // err == nil -// return 0, fmt.Errorf("Invalid listener_id format in token") -// } -// listenerId = int(listenerIdFloat) -// } else { -// c.JSON(http.StatusBadRequest, gin.H{"error": "listener_id not found in token"}) -// return 0, err -// } -// } -// return listenerId, err -// } - -// // /users/profile -// func (h *Handler) GetListenerProfile(c *gin.Context) { -// tokenLId, err := TakeListenerIdFromJWT(c) - -// ListenerInfo, err := domain.FindUserByListenerId(h.DB, tokenLId) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "Error fetching listener info"}) -// return -// } - -// fmt.Printf("ListenerInfo = %v \n", ListenerInfo) - -// c.JSON(http.StatusOK, gin.H{ -// "ListenerId": ListenerInfo.ListenerId, -// "ListenerName": ListenerInfo.ListenerName, -// "CreatedAt": ListenerInfo.CreatedAt, -// "UpdatedAt": ListenerInfo.UpdatedAt, -// "Email": "secret", -// "Password": "secret", -// "message": "got urself infomation", -// }) -// } - -// // ログアウト -// func LogoutHandler(c *gin.Context) { -// fmt.Print("LogoutHandlerの中") -// c.SetCookie("auth-token", "none", -1, "/", "localhost", false, true) - -// c.JSON(http.StatusOK, gin.H{ -// "message": "Successfully Logged Out", -// }) -// } - -// // lister_id = 3 はゲストアカウントにつき、退会不可。 -// func Withdrawal(c *gin.Context) { -// tokenLId, err := TakeListenerIdFromJWT(c) -// fmt.Printf("tokenLId = %v \n", tokenLId) -// if err != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": "Invalid ListenerId of token", -// "err": err, -// }) -// return -// } else if tokenLId == 3 { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": "ゲストアカウントは退会できません。", -// }) -// return -// } -// var dummyLi domain.Listener -// dummyLi.ListenerId = tokenLId -// result := Db.Delete(&dummyLi) -// if result.Error != nil { -// c.JSON(http.StatusBadRequest, gin.H{ -// "message": "Invalid Withdrawn", -// "err": result.Error, -// }) -// return -// } -// c.SetCookie("auth-token", "none", -1, "/", "localhost", false, true) -// c.JSON(http.StatusOK, gin.H{ -// "message": "Successfully Withdrawn", -// }) -// } - -// // lister_id = 3, listener_name = guest -// func GestlogIn(c *gin.Context) { -// trigerSetCookiebyUserAuth(c, 3) -// c.JSON(http.StatusOK, gin.H{ -// "message": "Successfully Guest Logged In", -// "listenerId": "3", -// "listenerName": "guest", -// }) -// } diff --git a/test0015Go/sample/for_rang.go b/test0015Go/sample/for_rang.go index e51f8c3..244e57f 100644 --- a/test0015Go/sample/for_rang.go +++ b/test0015Go/sample/for_rang.go @@ -35,7 +35,7 @@ var likeCnts = []LikeCount{ } // 結果 panic -func test1(c *gin.Context) { +func Test1(c *gin.Context) { var movieWithLikeCnts []MovieWithLikeCnt for i, movie := range movies { @@ -67,7 +67,7 @@ type MovieWithLikeCnt struct { LikeCnt int } -func test2(c *gin.Context) { +func Test2(c *gin.Context) { var transmitData []MovieWithLikeCnt // {1, "imo", ":8080"}, {2, "me", ":3000"}, {3, "chumu", ":80"}, @@ -99,7 +99,7 @@ type MovieWithLikeCnt2 struct { LikeCnt int } -func test3(c *gin.Context) { +func Test3(c *gin.Context) { var transmitData []MovieWithLikeCnt2 for _, movie := range movies { @@ -130,8 +130,8 @@ func returnLikeCntEachMovieId(movieId int, likeCnts []LikeCount) LikeCount { return LikeCount{MovieId: movieId, Count: 0} } -// test2の処理目視用 -func test2a(c *gin.Context) { +// Test2の処理目視用 +func Test2a(c *gin.Context) { // transmitData を作成 var transmitData []MovieWithLikeCnt diff --git a/test0015Go/sample/type_json.go b/test0015Go/sample/type_json.go new file mode 100644 index 0000000..524fbc2 --- /dev/null +++ b/test0015Go/sample/type_json.go @@ -0,0 +1,192 @@ +package sample + +import ( + "fmt" + "net/http" + "os" + + "github.com/gin-gonic/gin" + "github.com/joho/godotenv" + "gorm.io/driver/mysql" + "gorm.io/gorm" + // "github.com/sharin-sushi/0015docker/infra" +) + +// 下部にinit関数が2つ + +type ListenerId int +type VtuberId int + +type Vtuber struct { + VtuberId VtuberId `gorm:"primaryKey;type:int(11)"` //`json:"vtuber_id"` + VtuberName string `gorm:"type:varchar(50);not null;unique"` //`json:"vtuver_name"` + VtuberKana string `gorm:"type:varchar(50);unique"` //`json:"vtuber_kana"` + IntroMovieUrl string `gorm:"type:varchar(100)"` //`json:"vtuber_intro_movie_url"` + VtuberInputterId ListenerId `gorm:"type:int(11);not null"` //`json:"vtuber_inputter_id"` +} + +type Movie2 struct { + MovieUrl string `gorm:"primaryKey;type:varchar(100)"` //`json:"movie_url"` + MovieTitle string `gorm:"type:varchar(200);not null"` //`json:"movie_title"` + VtuberId VtuberId `gorm:"type:int(11);not null"` //`json:"vtuber_id"` + MovieInputterId ListenerId `gorm:"type:int(11);not null"` //`json:"movie_inputter_id"` /new +} +type VtuberMovie struct { + Vtuber + Movie2 +} +type VtuberSliceMovie struct { + Vtuber + Movie []Movie2 +} + +func AlterMainType(c *gin.Context) { + data, _ := GetVtubersMovies() + + fmt.Printf("data=%v", data) + + c.JSON(http.StatusBadRequest, gin.H{ + "data": data, + }) +} + +// localhost:80/type/vt-slise +func GetVtubersMovies() ([]VtuberSliceMovie, error) { + var Mos []Movie2 + // var VtsMos []VtuberMovie + var VtsSlMos []VtuberSliceMovie + selectQ := "vtuber_id, vtuber_name, movie_url, movie_title" + joinsQ := "LEFT JOIN vtubers USING(vtuber_id)" + err := db.Model(Mos).Select(selectQ).Joins(joinsQ).Scan(&VtsSlMos).Error + if err != nil { + return nil, err + } + return VtsSlMos, nil +} + +// 結果 // + +/////// コード +// selectQ := "vtuber_id, vtuber_name, movie_url, movie_title" +// joinsQ := "LEFT JOIN vtubers USING(vtuber_id)" +// err := db.Model(Mos).Select(selectQ).Joins(joinsQ).Scan(&VtsSlMos).Error +///////ログ +// invalid field found for struct github.~~~/sample.VtuberMovie's field Movie: define a valid foreign key for relations or implement the Valuer/Scanner interface +// SELECT vtuber_id, vtuber_name, movie_url, movie_title FROM +// `movie2` LEFT JOIN vtubers USING(vtuber_id) +// Postmanで受け取ったjsonデータ +// { "data": null} + +//////コード +// selectQ := "vtuber_id, vtuber_name, movie_url, movie_title" +// joinsQ := "LEFT JOIN vtubers USING(vtuber_id)" +// err := db.Model(Mos).Select(selectQ).Joins(joinsQ).Scan(&VtsMos).Error +//////ログ +// SELECT vtuber_id, vtuber_name, movie_url, movie_title FROM `movie2` LEFT JOIN vtubers USING(vtuber_id) +// data=[{{1 妹望おいも 0} {url1 0 0}} {{1 妹望おいも 0} {url2 0 0}}] +//////Postmanにて受け取ったjsonデータ +// { +// "data": [ +// {"VtuberName": "妹望おいも", "VtuberKana": "", "IntroMovieUrl": "", "VtuberInputterId": 0, "MovieUrl": "url1", "MovieTitle": "", "MovieInputterId": 0}, +// {"VtuberName": "妹望おいも", "VtuberKana": "", "IntroMovieUrl": "", "VtuberInputterId": 0, "MovieUrl": "url2", "MovieTitle": "", "MovieInputterId": 0 } +// ] +// } + +///////////////データ準備//////////////// +func preparedata() { + var vt1 = Vtuber{ + VtuberName: "妹望おいも", + VtuberKana: "imomochi_oimo", + VtuberInputterId: 1, + } + db.Create(&vt1) + + var mo1 = Movie2{ + MovieUrl: "url1", + VtuberId: 1, + } + var mo2 = Movie2{ + MovieUrl: "url2", + VtuberId: 1, + } + + db.Create(&mo1) + db.Create(&mo2) +} + +// 実際のクエリ +// INSERT INTO `vtubers` (`vtuber_name`,`vtuber_kana`,`intro_movie_url`,`vtuber_inputter_id`) VALUES ('妹望おいも','imomochi_oimo','','1') +// INSERT INTO `movie2` (`movie_url`,`movie_title`,`vtuber_id`,`movie_inputter_id`) VALUES ('url1','','1','0') +// NSERT INTO `movie2` (`movie_url`,`movie_title`,`vtuber_id`,`movie_inputter_id`) VALUES ('url2','','1','0') + +// コマンドプロンプトでデータ確認 + +// mysql> select * from vtubers; +// +-----------+-----------------+---------------+-----------------+--------------------+ +// | vtuber_id | vtuber_name | vtuber_kana | intro_movie_url | vtuber_inputter_id | +// +-----------+-----------------+---------------+-----------------+--------------------+ +// | 1 | 妹望おいも | imomochi_oimo | | 1 | +// +-----------+-----------------+---------------+-----------------+--------------------+ + +// mysql> select * from movie2; +// +-----------+-------------+-----------+-------------------+ +// | movie_url | movie_title | vtuber_id | movie_inputter_id | +// +-----------+-------------+-----------+-------------------+ +// | url1 | | 1 | 0 | +// | url2 | | 1 | 0 | +// +-----------+-------------+-----------+-------------------+ + +///////////////////////////// + +// DB接続 +var db *gorm.DB + +func init() { + godotenv.Load("../.env") +} + +// CREATE DATABASE test; +// GRANT ARLL ON *.* TO 'user' WITH GRANT OPTIOM; +func init() { + user := os.Getenv("MYSQL_USER") + pw := os.Getenv("MYSQL_PASSWORD") + // db_name := os.Getenv("MYSQL_DATABASE") + db_name := "test" + port := "localhost:3306" + + path := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true", user, pw, port, db_name) + fmt.Printf("path=%v \n", path) + var err error + db, err = gorm.Open(mysql.Open(path), &gorm.Config{}) + db = db.Debug() + if err != nil { + panic("failed to connect database") + } + + migration() + requestLogger() + + // preparedata() // 取得する用のデータ準備 初回のみ実施する + +} + +func migration() { + fmt.Print("migratoin開始") + db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate( + // User + // Listener{}, + // Like Relatoin + // Favorite{}, Follow{}, + // Vtuber Contents + // Karaoke{}, + Movie2{}, Vtuber{}, + // OriginalSong{}, + ) +} + +func requestLogger() gin.HandlerFunc { + return func(c *gin.Context) { + fmt.Printf("Method: %s, Path: %s, Header: %v\n, , Body: %v\n", c.Request.Method, c.Request.URL.Path, c.Request.Header, c.Request.Body) + c.Next() + } +}