无法从Go中的另一个包定义接收器

时间:2016-12-12 21:15:39

标签: database go package

我是Golang的初学者,无法理解这种语言中的一些概念。我非常喜欢它,但在网络上,每个例子都非常简单,并没有解释正确的开发方式。 所以,我想配置与MySQL的数据库连接。我使用文件dbconfig.go创建一个包dbconfig,使用interfaces文件创建包dastructure,使用实体文件创建另一个包init实体。 这是结构: enter image description here

main.go:

import (
    y "github.com/danyalov/shebeke/dbconfig"
    "github.com/danyalov/shebeke/routes"
    _ "github.com/go-sql-driver/mysql"
    "github.com/labstack/gommon/log"
)

func main() {
    db, err := y.InitDB("mysql", "root:root@tcp(localhost:3306)/dbtest?parseTime=true")
    if err != nil {
        log.Fatal(err)
    }
    e := routes.NewConnection(db)
    e.Logger.Fatal(e.Start(":9898"))
}

routes.go:

import (
    "github.com/danyalov/shebeke/datastructure"
    y "github.com/danyalov/shebeke/dbconfig"
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)

func NewConnection(db *y.DB) *echo.Echo {
    e := echo.New()
    env := Env{db}
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    e.GET("/contracts", env.GetContracts)
    e.GET("/contract/:id", env.GetContractByID)

    return e
}

type Env struct {
    contract datastructure.Contract
}

services.go:

import (
    "github.com/labstack/echo"
    "log"
    "net/http"
    "strconv"
)

func (env *Env) GetContracts(c echo.Context) error {
    contracts, err := env.contract.GetContracts()
    if err != nil {
        log.Fatal(err)
    }
    return c.JSON(http.StatusOK, &contracts)
}

dbconfig.go:

import (
    "database/sql"
    "fmt"
    "github.com/labstack/gommon/log"
)

type DB struct {
    *sql.DB
}

//InitDB initialize mysql database
func InitDB(driver, path string) (*DB, error) {
    db, err := sql.Open(driver, path)
    if err != nil {
        log.Fatal(err)
    }
    err = db.Ping()
    if err != nil {
        log.Fatal(err)
    } else {
        fmt.Println("Connected to DB")
    }
    return &DB{db}, err
}

数据结构/ contract.go:

import y "github.com/danyalov/shebeke/datastructure/entity"

type Contract interface {
    GetContracts() (y.Contracts, error)
    GetContractByID(id int) (y.Contract, error)
}

数据结构/实体/ contract.go:

import (
    "github.com/labstack/gommon/log"
    "time"
)

type Contract struct {
    ID         int       `json:"id"`
    State      string    `json:"state"`
    StartDate  time.Time `json:"start_date"`
    FinishDate time.Time `json:"finish_date"`
}

type Contracts []Contract

func (db *DB) GetContracts() (c Contracts, err error) {
    rows, err := db.Query("select * from contract")
    if err != nil {
        log.Fatal(err)
    }

    contract := Contract{}
    for rows.Next() {
        err = rows.Scan(&contract.ID, &contract.State, &contract.StartDate, &contract.FinishDate)
        c = append(c, contract)
    }
    return c, err
}

为什么我不能将数据库类型从dbconfig包导入实体包作为方法接收器?我得到Unresolved type 'DB'

这是这个项目的my working copy(Git),我把dbconfig.go放在实体中,但是我不喜欢它,我认为这对dbconfig文件来说不正确。

在GO中配置db的正确文件结构是什么?也许你在Git或一些教程中有自己的例子?

1 个答案:

答案 0 :(得分:5)

您只能在同一个包中定义的类型上定义方法。在这种情况下,您的DB类型是在dbconfig包中定义的,因此您的entity包无法在其上定义方法。

在这种情况下,您的选择是使GetContracts成为函数而不是方法并将*dbconfig.DB作为参数传递,或者通过在{{1中导入entity包来反转依赖性并在那里写GetContracts(作为方法或函数,以任何方式工作)。第二个实际上可能是更好的选择,因为从设计的角度来看,它打破了抽象,使得除数据库包之外的包创建SQL查询字符串。