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

Jac*_*iel 0 database package go

我是Golang的初学者,无法理解此语言中的某些概念。我非常喜欢它,但是在Web中,每个示例都非常简单,并且没有解释正确的开发方式。因此,我想配置与MySQL的数据库连接。我使用文件dbconfig.go创建一个包dbconfig,使用接口文件创建一个包dastructure,使用实体文件创建另一个包初始化实体。这是结构: 在此处输入图片说明

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"))
}
Run Code Online (Sandbox Code Playgroud)

route.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
}
Run Code Online (Sandbox Code Playgroud)

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)
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

datastructure / contract.go:

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

type Contract interface {
    GetContracts() (y.Contracts, error)
    GetContractByID(id int) (y.Contract, error)
}
Run Code Online (Sandbox Code Playgroud)

数据结构/实体/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
}
Run Code Online (Sandbox Code Playgroud)

为什么我不能将dbconfig包中的数据库类型作为方法接收者导入到实体包中?我懂了Unresolved type 'DB'

这是该项目的工作副本(Git),我将dbconfig.go放在实体中,但是我不喜欢它,我认为这对于dbconfig文件而言是不正确的位置。

在GO中配置数据库的正确文件结构是什么?也许您在Git或一些教程中有自己的示例?

Kae*_*dys 5

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

在这种情况下,您的选择是使GetContracts成为函数而不是方法,并将其*dbconfig.DB作为参数,或通过将entity包导入到其中dbconfig并在其中写入GetContracts 来反转依赖关系(以方法或函数的形式起作用)。实际上,第二个选项可能是更好的选择,因为从设计的角度来看,它破坏了抽象,使除数据库包之外的其他包都可以创建SQL查询字符串。