簡體   English   中英

使用帶有 golang 和數據庫抽象的接口

[英]Using interfaces with golang and database abstraction

我想弄清楚如何在 Go 中構建數據存儲抽象。 我想我了解接口的基礎知識。 但是,我遇到的問題是,網上的所有示例都只向您展示了最簡單的案例,除此之外別無他物。

我想要做的是弄清楚如何以及在哪里放置 SQL 代碼。 我試圖編寫最簡單的代碼來說明我想要做什么(是的,沒有錯誤代碼,是的,路徑結構不是慣用的)。 我有一個包含兩個表的數據庫。 一個用於存儲圓形,一個用於存儲正方形。 我在 Go 中有對象來制作這些。 我的目錄結構是:

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

我能想到的唯一方法是將 SQL INSERT 和 SELECT 代碼放在實際的形狀文件(circle.go 和 square.go)中。 但這感覺真的不對。 看起來它應該是 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.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
}

數據存儲/數據存儲.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. 
}

由於 Circle 和 Square 對象的數據庫表會有所不同,因此我需要為每個對象設置一個方法。 如果我向 circle 包和 square 包添加一個方法來進行插入,我可以讓它工作。 但就像我上面說的那樣,感覺就像我做錯了。

非常感謝。

類型切換是正確的做法。 您的邏輯代碼(您編寫的代碼是因為之前沒有其他人這樣做過)應該對存儲一無所知。

假設您想為請求添加一個計數器,並且您決定對 Redis 上的請求進行計數。 然后怎樣呢? 也將計數器集合名稱添加到 Shape 中?

然后,您應該創建一個新的 ShapeStorer 作為裝飾器,並在 put 方法中調用 Redis ShapeStorer 和 sqlite ShapeStorer。

對於 no-sql 數據庫,您有時根本不關心架構,您只需序列化對象並保存它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM