2017-10-24 13 views
1

나는 Go에서 데이터 저장소 추상화를 작성하는 방법을 알아 내려고하고 있습니다. 나는 인터페이스의 기초를 이해한다고 생각한다. 그러나, 내가 가진 문제는 모든 예제는 온라인으로 당신에게 가장 단순한 경우 만 보여줍니다.golang 및 데이터베이스 추상화와 인터페이스 사용

내가하려는 것은 SQL 코드를 넣는 방법과 장소를 파악하는 것입니다. 나는 내가하려고하는 것을 설명 할 수있는 가장 단순한 코드를 작성하려고 시도했다. (예, 오류 코드는 없다. 예, 경로 구조는 관용적이지 않다.) 두 테이블이있는 데이터베이스가 있습니다. 하나는 서클을 저장하고 다른 하나는 사각형을 저장합니다. 나는 이것을 만들기 위해 이동에있는 객체를 가지고 있습니다. 내 디렉토리 구조는 다음과 같습니다 내가이 일을하는 방법을 생각할 수

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 shapes 

type Shaper interface { 
    Area() float64 
} 

모양/원/circle.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 
} 

모양/square/square.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 
} 
,451,515,

데이터 저장소/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) 또는 ['Data Mapper' 패턴] (https://en.wikipedia.org/wiki/Data_mapper_pattern)을 선택할 수 있습니다. 전자에서는 * CRUD * 작업이 * object *의 일부로 정의되지만 나중에 * object *는 데이터 만 보유하고 지속성 계층 (데이터베이스)에 대해서는 알지 못합니다. – putu

+0

datastore/sqlite3/sqlite3.go의 객체 유형에 대해 switch 문을 수행하면 모든 SQL 문이 sqlite 패키지에 남아있을 수 있습니다. 주석에서 설명했듯이 다른 방법을 사용하면 데이터베이스 코드를 객체에 넣을 수 있습니다. 그러면 10 개의 다른 데이터 저장소를 지원해야 할 때 어떻게됩니까? 그냥 잘못된 것 같습니다. 또한이 작업을 더 잘 수행 할 수있는 간단한 트릭이 누락 된 것처럼 보입니다. – jordan2175

+0

* type switching *을 사용하여 솔루션을 제한하기 때문에 잘못되었습니다. 기존 ORM 패키지 (예 : [gorm] (https://github.com/jinzhu/gorm))를 사용할 수도 있고 직접 개발할 수도 있습니다. 나중에 * struct * name과 관련하여 테이블 네이밍을위한 * convention/rule *을 정의 할 것을 제안합니다. 예를 들어'CircleType'의 테이블 이름을'CircleType'이나'circle_type' 등으로 정의 할 수 있습니다. 그런 다음 태그를 사용하여 테이블의 컬럼 이름과 * struct *의 필드 이름 사이의 매핑을 정의하십시오. 이를 기반으로 리플렉션을 사용하여 * 데이터 저장소 * 내에서 간단한 CRUD에 대한 SQL을 생성 할 수 있습니다. – putu

답변

0

스위치는 올바른 작업입니다. 논리 코드 (이전에 본문을 작성하지 않았기 때문에 작성한 코드)는 저장 영역에 대해 아무것도 모르는 상태 여야합니다.

요청에 카운터를 추가하고 Redis에서 요청을 계산하기를 원할 것입니다. 그 때 무엇? 셰이프에 카운터 컬렉션 이름도 추가 하시겠습니까?

그러면 새 ShapeStorer을 장식 자로 만들고 put 메서드에서 Redis ShapeStorer 및 sqlite ShapeStorer을 호출해야합니다.

no-sql 데이터베이스의 경우 스키마를 신경 쓰지 않아도됩니다. 개체를 직렬화하고 저장하면됩니다.