나는 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.
}
방법. 삽입을 수행 할 원 패키지 및 정사각형 패키지에 메서드를 추가하면이 작업을 수행 할 수 있습니다. 그러나 내가 위에서 말했듯이, 내가 잘못하고있는 것처럼 느껴진다.
미리 감사드립니다.
나는 옳은/틀린 방법이 없다고 생각합니다. 그것은 스타일의 문제입니다. ['ActiveRecord' 패턴] (https://en.wikipedia.org/wiki/Active_record_pattern) 또는 ['Data Mapper' 패턴] (https://en.wikipedia.org/wiki/Data_mapper_pattern)을 선택할 수 있습니다. 전자에서는 * CRUD * 작업이 * object *의 일부로 정의되지만 나중에 * object *는 데이터 만 보유하고 지속성 계층 (데이터베이스)에 대해서는 알지 못합니다. – putu
datastore/sqlite3/sqlite3.go의 객체 유형에 대해 switch 문을 수행하면 모든 SQL 문이 sqlite 패키지에 남아있을 수 있습니다. 주석에서 설명했듯이 다른 방법을 사용하면 데이터베이스 코드를 객체에 넣을 수 있습니다. 그러면 10 개의 다른 데이터 저장소를 지원해야 할 때 어떻게됩니까? 그냥 잘못된 것 같습니다. 또한이 작업을 더 잘 수행 할 수있는 간단한 트릭이 누락 된 것처럼 보입니다. – jordan2175
* type switching *을 사용하여 솔루션을 제한하기 때문에 잘못되었습니다. 기존 ORM 패키지 (예 : [gorm] (https://github.com/jinzhu/gorm))를 사용할 수도 있고 직접 개발할 수도 있습니다. 나중에 * struct * name과 관련하여 테이블 네이밍을위한 * convention/rule *을 정의 할 것을 제안합니다. 예를 들어'CircleType'의 테이블 이름을'CircleType'이나'circle_type' 등으로 정의 할 수 있습니다. 그런 다음 태그를 사용하여 테이블의 컬럼 이름과 * struct *의 필드 이름 사이의 매핑을 정의하십시오. 이를 기반으로 리플렉션을 사용하여 * 데이터 저장소 * 내에서 간단한 CRUD에 대한 SQL을 생성 할 수 있습니다. – putu