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

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

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

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Q&A

0回答

1361閲覧

golang(ORM:gorm)で、構造体の設計と実装を簡潔にしたい。

umino

総合スコア54

Go

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

0グッド

0クリップ

投稿2021/04/07 14:10

前提・実現したいこと

golang(フレームワークはginです)で、
DBへinsertする際のstructやfunctionについて、より簡潔に、わかりやすく、疎結合に書きたいです。
しかし知見がなく、お詳しい方、良い方法をご教示願えませんでしょうか。

前提としては、下記のようなstructがあります。ORMはgormです。

go

1package entity 2 3import "github.com/jinzhu/gorm" 4 5// マイグレーション用 6type Post struct { 7 UserId uint64 `gorm:"type:int; "` //型は変更不可 8 PostImageId int `gorm:"type:int; "`//型は変更不可 9 DogName string `gorm:"type:varchar(30); "`//型は変更不可 10 OtherMessage string `gorm:"type:varchar(4000);"`//型は変更不可 11}

go

1package main 2router.POST("/addRecord", controller.Create)// レコードをDBへ登録する

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

controllerでは、クライアントから受けたパラメタを
上記に示したstructentity.Post(マイグレーション用の構造体)型の変数recordに入れ、
下記の通りDBへInsertしています。
ここで面倒なこととして、受けたパラメタはstring型
entity.Postの各フィールドはuint型int型があるため、全て各フィールドに沿った変換をする必要があります。

go

1package controller 2 3func Create(c *gin.Context) { 4 userId, _ := strconv.ParseUint(c.PostForm("user_id"), 10, 64) //stringからUintに変換する 5 postImageId, _ := strconv.ParseInt(c.PostForm("post_image_id")) //stringからintに変換する 6 7 // テーブルに登録するためのレコード情報 8 var record = entity.Post{ 9 UserId: userId, //変換したUintを格納する 10 PostImageId: postImageId,//変換したintを格納する 11 DogName: c.PostForm("dog_name"), 12 OtherMessage: c.PostForm("other_message"), 13 } 14 db.InsertRecord(&record) // -> 下記コードブロックへ 15 c.JSON(http.StatusCreated, "*****created") 16}

go

1package db 2 3func InsertRecord(registerRecord *entity.Post) { //entity.Post型の引数で受ける 4 db := open() 5 db.Create(&registerRecord) // insert 6 defer db.Close() 7}

controllerで行っているこの型変換作業の羅列は美しくなく(実際は膨大な量のフィールドを変換しています)、
またマイグレーション用のstructをCRUDにも使っていることは、あまりよくないと感じています。

試したこと

以下、テーブル設計のためのstructと、insertのためのstructを切り分けるために、私が考えた案です。
お詳しいかた、どのような方法が賢いか、ご教示願えませんでしょうか。


案A:INSERT用のstructを使用する。
今使用しているstructentity.Post(マイグレーション用struct)を使用せず、
entity.DTOPostというstructを用意します。
全てstringなので、Create()では、受けたパラメタを変換せずそのまま格納できます。

go

1package entity 2 3// CRUD用(編集中) 4type DTOPost struct { 5 UserId string 6 PostImageId string 7 DogName string 8 OtherMessage string 9}

しかし、gorm(ORM)の機能上、struct名がそのままinsert先のテーブル名指定になります
つまり、ここでは本当はPostテーブルにinsertしたいが、DTOPostテーブルにinsertしてしまうことになります。
公式をみたところ、insert先のテーブル名を指定できる機能はなさそうでした。
https://gorm.io/ja_JP/docs/create.html


案B:パッケージを分ける
同じパッケージに同名structを持つことはできないので、
ディレクトリ(パッケージ)を分けて、structPostを作成する。

go

1package other 2 3// CRUD用(編集中) 4type Post struct { 5 UserId string 6 PostImageId string 7 DogName string 8 OtherMessage string 9}

go

1package db 2 3func InsertRecord(registerRecord *other.Post) { //other.Post型の引数で受ける 4 db := open() 5 db.Create(&registerRecord) // insert 6 defer db.Close() 7}

(B案は試していませんが、洗練された方法ではないかな、と感じています。)


案C:その他


今はinsertのためにマイグレーション用structをそのまま使っており、
そもそもマイグレーション用の構造体をinsertでも使用することに違和感もあります。

長々とすみません、
お詳しいかた、どのような方法が賢いか、ご教示願えませんでしょうか。

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問