2017-10-24 26 views
1

私は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. 
} 

データベーステーブルには、サークルや広場オブジェクトに対して異なるものになりますので、私が持っている必要がありますどのようにいくつかの方法挿入を行うためにサークルパッケージと正方形パッケージにメソッドを追加すると、これを動作させることができます。しかし、私が上記のように、それは私が間違っているように感じる。

ありがとうございます。

+0

私は、右か間違い*アプローチがないと思います。それはスタイルの問題です。 ['ActiveRecord'パターン](https://en.wikipedia.org/wiki/Active_record_pattern)、['データマッパー 'パターン](https://en.wikipedia.org/wiki/Data_mapper_pattern)を選択することができます。前者では、* CRUD *操作は*オブジェクト*の一部として定義され、後の*オブジェクト*はデータのみを保持し、永続層(データベース)については何も知らない。 – putu

+0

datastore/sqlite3/sqlite3.goのオブジェクト型に対してswitch文を実行すると、すべてのSQL文がsqliteパッケージに残ります。コメントに例を示したように、逆にすると、オブジェクトにデータベースコードが追加されます。次に、10種類のデータストアをサポートする必要があるときにはどうなりますか。それは間違っているようです。また、私はこの仕事をより良くするためのすっきりしたトリックが欠けているようです。 – jordan2175

+0

*タイプ切替*を使って解決策を制限するので間違っているようです。既存のORMパッケージ([gorm](https://github.com/jinzhu/gorm)など)を使用することもできます。独自のORMパッケージを使用することもできます。後のケースでは、* struct * nameとの関係で表の命名規則を定義することをお勧めします。例えば、 'CircleType'のテーブル名を' CircleType'や 'circle_type'などと定義することができます。タグを使ってテーブルのカラム名と* struct *のフィールド名の間のマッピングを定義します。これらに基づいて、リフレクションを使用して*データストア*内の単純なCRUDのSQLを構築できます。 – putu

答えて

0

スイッチが正しいことです。 あなたのロジックコード(あなたが以前に何もしていなかったので書いたもの)は、ストレージについては何も知りません。

リクエスト用のカウンタを追加し、レディスでリクエストをカウントすることにします。それでは?シェイプにカウンタコレクション名も追加しますか?

次に、新しいShapeStorerをデコレータとして作成し、putメソッドでRedis ShapeStorerとsqlite ShapeStorerを呼び出す必要があります。

no-sqlデータベースの場合、オブジェクトをシリアル化して保存するだけで、スキーマは気にしないことがあります。

関連する問題