gpt4 book ai didi

go - 克服 Go 中不允许的导入周期

转载 作者:数据小太阳 更新时间:2023-10-29 03:13:47 30 4
gpt4 key购买 nike

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

我的情况是这样的:我曾经将模型和 Controller 分开,在我的模型包中我有一个包含所有模型函数接口(interface)的 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
}

一切都很好,因为模型函数也位于模型包中,所以我在 Controller 包中的函数可以自由调用 models.DB.CreateUser(ctx, "username", []byte("password ")).

现在,我决定将上述所有代码移动到datastore 包中,而CreateUser 的模型位于user 中包裹。换句话说,package user现在包含controller和model函数,其中controller相关函数依赖于datastore包,而DSDatabase接口(interface)依赖于 user 模型函数。

我真的很感激帮助弄清楚如何克服导入周期,同时保持 DSDatastore 接口(interface)与所有其他包(如 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 包中,我在与 Controller 相关的文件中有这个:

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
}

这当然会导致导入循环,遗憾的是我不知道如何克服......

最佳答案

首先,您不能在 package A 中为 package B 中声明的类型定义方法。

所以这个...

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
}

...甚至不应该编译。

这里...

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)
}

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


关于您的问题...您可以做的一件事是在 user 包中定义 Datastore 接口(interface),并将实现放在另一个包中,这有助于当您需要一个接口(interface)的不同实现时,它本身就很好。如果你这样做,你的 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"))
}

接口(interface)实现包:

package datastore

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

// DB implements the user.DSDatabase interface.
type DB struct { /* ... */ }

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

func init() {
// make sure to initialize the user.DB variable that
// is accessed by the CreateUserPOST func or else you'll
// get nil reference panic.
user.DB = &DB{}
}

关于go - 克服 Go 中不允许的导入周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43300723/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com