私はGoでデータストアの抽象化を構築する方法を理解しようとしています。私はインターフェイスの基本を理解していると思う。しかし、私が抱えている問題は、すべての例題がオンラインでしかないということです。golangとデータベース抽象化でのインターフェイスの使用
私がしようとしていることは、SQLコードをどこにどこに置くかを理解することです。私は何をしようとしているのかを示すことができる最も単純なコードを書こうとしました(はい、エラーコードはありません、はい、パス構造は慣習的ではありません)。私は2つのテーブルを持つデータベースを持っています。サークルを保存する1つ、四角を保存する1つ。私はこれらを作るためにゴーにオブジェクトを持っています。私のディレクトリ構造は次のとおりです。
project/main.go
project/test.db
project/shapes/shape.go
project/shapes/circle/circle.go
project/shapes/square/square.go
project/datastore/datastore.go
project/datastore/sqlite3/sqlite3.go
私はこの仕事をするためにどのように考えることができる唯一の方法は、実際の形状ファイル(circle.goとsquare.go)の内部でSQLのINSERTとSELECTコードを配置することです。しかし、それは本当に間違っていると感じます。それはdatastore/sqlite3パッケージの一部でなければならないようです。私はちょうどその仕事をする方法を見ていない。ここで私はこれまで持っているものです。
main.go
package main
import (
"fmt"
"project/datastore/sqlite3"
"project/shapes/circle"
"project/shapes/square"
)
func main() {
c := circle.New(4)
area := c.Area()
fmt.Println("Area: ", area)
s := square.New(12)
area2 := s.Area()
fmt.Println("Area: ", area2)
db := sqlite3.New("test.db")
db.Put(c)
db.Close()
}
形状/ shape.go
package circle
import (
"project/shapes"
)
type CircleType struct {
Radius float64
}
func New(radius float64) shapes.Shaper {
var c CircleType
c.Radius = radius
return &c
}
func (c *CircleType) Area() float64 {
area := 3.1415 * c.Radius * c.Radius
return area
}
形状circle.go
package shapes
type Shaper interface {
Area() float64
}
形状/サークル/ /正方形/正方形.go
package square
import (
"project/shapes"
)
type SquareType struct {
Side float64
}
func New(side float64) shapes.Shaper {
var s SquareType
s.Side = side
return &s
}
func (s *SquareType) Area() float64 {
area := s.Side * s.Side
return area
}
データストア/ datastore.go
package datastore
import (
"project/shapes"
)
type ShapeStorer interface {
Put(shape shapes.Shaper)
Close()
}
データストア/ sqlite3の/ sqlite3.go
package sqlite3
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
"log"
"project/datastore"
"project/shapes"
)
type Sqlite3DatastoreType struct {
DB *sql.DB
}
func New(filename string) datastore.ShapeStorer {
var ds Sqlite3DatastoreType
db, sqlerr := sql.Open("sqlite3", filename)
if sqlerr != nil {
log.Fatalln("Unable to open file due to error: ", sqlerr)
}
ds.DB = db
return &ds
}
func (ds *Sqlite3DatastoreType) Close() {
err := ds.DB.Close()
if err != nil {
log.Fatalln(err)
}
}
func (ds *Sqlite3DatastoreType) Put(shape shapes.Shaper) {
log.Println("Help")
// here you could either do a switch statement on the object type
// or you could do something like shape.Write(), if Write() was defined
// on the interface of shape/shapes.go Shaper interface and then
// implemented in the Square and Circle objects.
}
データベーステーブルには、サークルや広場オブジェクトに対して異なるものになりますので、私が持っている必要がありますどのようにいくつかの方法挿入を行うためにサークルパッケージと正方形パッケージにメソッドを追加すると、これを動作させることができます。しかし、私が上記のように、それは私が間違っているように感じる。
ありがとうございます。
私は、右か間違い*アプローチがないと思います。それはスタイルの問題です。 ['ActiveRecord'パターン](https://en.wikipedia.org/wiki/Active_record_pattern)、['データマッパー 'パターン](https://en.wikipedia.org/wiki/Data_mapper_pattern)を選択することができます。前者では、* CRUD *操作は*オブジェクト*の一部として定義され、後の*オブジェクト*はデータのみを保持し、永続層(データベース)については何も知らない。 – putu
datastore/sqlite3/sqlite3.goのオブジェクト型に対してswitch文を実行すると、すべてのSQL文がsqliteパッケージに残ります。コメントに例を示したように、逆にすると、オブジェクトにデータベースコードが追加されます。次に、10種類のデータストアをサポートする必要があるときにはどうなりますか。それは間違っているようです。また、私はこの仕事をより良くするためのすっきりしたトリックが欠けているようです。 – jordan2175
*タイプ切替*を使って解決策を制限するので間違っているようです。既存のORMパッケージ([gorm](https://github.com/jinzhu/gorm)など)を使用することもできます。独自のORMパッケージを使用することもできます。後のケースでは、* struct * nameとの関係で表の命名規則を定義することをお勧めします。例えば、 'CircleType'のテーブル名を' CircleType'や 'circle_type'などと定義することができます。タグを使ってテーブルのカラム名と* struct *のフィールド名の間のマッピングを定義します。これらに基づいて、リフレクションを使用して*データストア*内の単純なCRUDのSQLを構築できます。 – putu