Go中不允许克服导入周期

时间:2017-04-08 21:51:54

标签: go google-cloud-datastore

我理解问题,根据答案here,但是,我真的可以使用帮助或更详细的代码解释它是如何克服的。

我的情况是这样的:我曾经将模型和控制器分开,在我的模型包中,我有一个datastore.go文件,其中包含所有模型函数的接口:

package models

type DSDatabase interface {
    CreateUser(ctx context.Context, username string, password []byte) (*datastore.Key, error)
    // More model functions
}

type datastoreDB struct {
    client *datastore.Client
}

var (
    DB DSDatabase
    _  DSDatabase = &datastoreDB{}
)

func init() {
    // init datastore
}

这很好,因为模型函数也位于模型包中,因此我在控制器包中的函数可以自由调用models.DB.CreateUser(ctx, "username", []byte("password"))

现在,我已决定将上述所有代码移至datastore包,而CreateUser的模型位于user包中。换句话说,package user现在包含控制器和模型函数,控制器相关函数依赖于datastore包,而DSDatabase接口依赖于user模型函数

我非常感谢帮助确定如何克服导入周期,同时保持DSDatastore界面与homeuser等所有其他包分开。

如果上述内容不够清楚,则上述代码已更改为:

package datastore

import (
    "github.com/username/projectname/user"
)

type DSDatabase interface {
    user.CreateUser(ctx context.Context, username string, passwoUserRegister(ctx context.Context, username string, password []byte) (*datastore.Key, error)
}

...

在我的user包中,我在控制器相关文件中有这个:

package user

import (
    "github.com/username/projectname/datastore"
)

func CreateUserPOST(w http.ResponseWriter, r *http.Request) {
    // get formdata and such
    datastore.DB.CreateUser(ctx, "username", []byte("password"))
}

在另一个与模型相关的文件中我有:

package user

import (
    "github.com/username/projectname/datastore"
)

func (db *datastore.datastoreDB) CreateUser(ctx context.Context, username string) (*User, error) {
    key := datastore.NameKey("User", username, nil)
    var user User
    err := db.client.Get(ctx, key, &user)
    if err != nil {
        return nil, err
    }
    return &user, nil
}

这当然会导致进口周期,我很遗憾无法弄清楚如何克服..

1 个答案:

答案 0 :(得分:1)

首先,您无法在包装B 中声明的类型中使用 pacakge A 定义方法。

所以这......

ErrHandler:

......甚至不应该编译。

这就是......

package user

import (
    "github.com/username/projectname/datastore"
)

func (db *datastore.datastoreDB) CreateUser(ctx context.Context, username string) (*User, error) {
    key := datastore.NameKey("User", username, nil)
    var user User
    err := db.client.Get(ctx, key, &user)
    if err != nil {
        return nil, err
    }
    return &user, nil
}

......这也是无效的Go代码。

关于你的问题......你可以做的一件事是在package datastore import ( "github.com/username/projectname/user" ) type DSDatabase interface { user.CreateUser(ctx context.Context, username string, passwoUserRegister(ctx context.Context, username string, password []byte) (*datastore.Key, error) } 包中定义Datastore接口并将实现置于另一个包中,这很适合你需要的时候一个接口的不同实现。如果您执行此操作,user包不再需要了解user包,datastore包仍然必须知道datastore包,但这是一个行。

一个例子:

user

具有接口实现的包:

package user

import (
    "context"
)

type DSDatabase interface {
    CreateUser(ctx context.Context, username string, password []byte) (*User, error)
    // ...
}

// This can be set by the package that implements the interface
// or by any other package that imports the user package and
// a package that defines an implementation of the interface.
var DB DSDatabase

type User struct {
    // ...
}

func CreateUserPOST(w http.ResponseWriter, r *http.Request) {
    // get formdata and such
    DB.CreateUser(ctx, "username", []byte("password"))
}