我理解问题,根据答案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
界面与home
和user
等所有其他包分开。
如果上述内容不够清楚,则上述代码已更改为:
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
}
这当然会导致进口周期,我很遗憾无法弄清楚如何克服..
答案 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"))
}