Oop 在Golang中使用结构并将其视为类来解决依赖关系是否不好?

Oop 在Golang中使用结构并将其视为类来解决依赖关系是否不好?,oop,go,struct,dependency-injection,dependencies,Oop,Go,Struct,Dependency Injection,Dependencies,我以前用OOP框架写过很多PHP,我正在学习Golang 当我使用PHP时,类非常有用,我可以将$model传递到我的类中,然后在函数之间共享它: class User { function __construct(UserModel $model) { $this->model = $model } function delete($id) { $this->model->delete($id); } functi

我以前用OOP框架写过很多PHP,我正在学习Golang

当我使用PHP时,
非常有用,我可以将
$model
传递到我的类中,然后在函数之间共享它

class User {
   function __construct(UserModel $model) {
       $this->model = $model
   }

   function delete($id) {
       $this->model->delete($id);
   }

   function update($id) {
       $this->model->update($id);
   }
}

$UserModel = new UserModel();
$User      = new User($UserModel);
$User->delete(1);
但是在Golang中没有
,我知道我可以像对待类一样对待结构:

type User struct {
    model *models.User
}

func (u *User) Delete(id int) {
    u.model.Delete(id)
}

func (u *User) Update(id int) {
    u.model.Update(id)
}

userModel := &models.User{}
user      := User{model: userModel}
user.Delete(1)
我觉得
struct
是用来存储信息的,而应该使用struct的方法来修改struct的值


但是现在我创建了一个struct,只是因为我想把它当作一个类来对待,并且解决依赖性问题,在Golang中使用这种方法不好吗?

从总体概念上看,您的实现没有错

从细节上看,有一些不一致之处会引起问题

在下面的所有情况下,由于在各种删除调用中共享数据,存在潜在的并发问题

案例A 如果models.User{}完成了所有的工作,那么为什么我们不能

userModel := &models.User{}
userModel.Delete(userId)
案例B 如果用户是我们的公共界面:

user      := User{model: userModel}
user.Delete(1)
那么,删除用户ID是多余的,应按照以下步骤进行:

user.Delete()
用户ID取自用户上下文

案例C 否则,我们可能希望为所有用户实例设置userModel:

package User;
// private package level variable
var model = userModel
func Delete(userId int) {
    model.Delete(userId)
}
...
User.Delete(userId)
结论
上述每种情况都以略微不同的侧重点解决了相同的问题。案例A很简单。案例B和C依赖于可与事件通知一起使用的底层共享代码。案例B和案例C的用户范围不同。在案例B中,用户是一个结构。在案例C中,user是一个包名。我认为案例C的使用频率低于案例B。因此,如果use坚持使用底层模型,那么从用户代码的角度来看,案例B可能是最直观的解决方案。

从总体概念的角度来看,您的实现没有错

从细节上看,有一些不一致之处会引起问题

在下面的所有情况下,由于在各种删除调用中共享数据,存在潜在的并发问题

案例A 如果models.User{}完成了所有的工作,那么为什么我们不能

userModel := &models.User{}
userModel.Delete(userId)
案例B 如果用户是我们的公共界面:

user      := User{model: userModel}
user.Delete(1)
那么,删除用户ID是多余的,应按照以下步骤进行:

user.Delete()
用户ID取自用户上下文

案例C 否则,我们可能希望为所有用户实例设置userModel:

package User;
// private package level variable
var model = userModel
func Delete(userId int) {
    model.Delete(userId)
}
...
User.Delete(userId)
结论
上述每种情况都以略微不同的侧重点解决了相同的问题。案例A很简单。案例B和C依赖于可与事件通知一起使用的底层共享代码。案例B和案例C的用户范围不同。在案例B中,用户是一个结构。在案例C中,user是一个包名。我认为案例C的使用频率低于案例B。因此,如果use坚持使用底层模型,那么从用户代码的角度来看,案例B可能是最直观的解决方案。

您可以使用带有方法的界面 在用(连接数据库)

在用户控制器中

// UserController controller
type UserController struct {
    Service services.UserServiceInterface
}
    func (controller UserController) GetAll(c *gin.Context) {
    users, errGetAll := controller.Service.GetAll(params)
}

您可以将接口与方法一起使用 在用(连接数据库)

在用户控制器中

// UserController controller
type UserController struct {
    Service services.UserServiceInterface
}
    func (controller UserController) GetAll(c *gin.Context) {
    users, errGetAll := controller.Service.GetAll(params)
}

我不确定你到底在问什么,但我看不出你所做的有任何错误(除了将
int
传递给那些函数而不是
id
——它不会按原样编译)。噢,谢谢你的更正,就像我说的,我来自OOP背景,但我不确定是否应该带上我的“旧想法”对于新的语言,因为我听到了很多关于“不要在Golang中使用OOP”,这就是为什么我不确定我这样做是正确的还是错误的。我认为告诫不要在Go中使用OOP是愚蠢的。显然,GO不是C++或java模型中的一种典型的面向对象语言,但它确实有一些特性,允许您在开发软件时使用OO原则。正如您所说,Go没有传统的类,但它有结构、接口、带接收器的方法和嵌入,所有这些都允许您执行与OO语言类似的操作。一些值得注意的例外是没有构造函数和析构函数,也没有子类化的直接等价物(尽管嵌入是类似的);您当然可以将结构定义视为类,将该结构的实例视为对象;你可能想要一个
func-NewUser(m*models.User)User{…}
@Plato我以前考虑过使用
func-NewUser(m*models.User)User{…}
,但是我必须在我的函数中传递
models.User
,另外,如果我想为函数添加一个新参数,它是不灵活的。我不确定你到底在问什么,但是我看不出你所做的有任何错误(除了将
int
传递给那些函数而不是
id
——它不会按原样编译)。噢,谢谢你的更正,就像我说的,我来自OOP背景,但我不确定我是否应该将我的“旧想法”带到新语言中,因为我听过很多关于“不要在Golang中使用OOP,这就是为什么我不确定我做的是对还是错的原因。我认为告诫不要在围棋中使用OOP是愚蠢的。显然,GO不是C++或java模型中的一种典型的面向对象语言,但它确实有一些特性,允许您在开发软件时使用OO原则。正如您所说,Go没有传统的类,但它有结构、接口、带接收器的方法和嵌入,所有这些都允许您执行与OO语言类似的操作。一些值得注意的例外是没有构造函数和析构函数,也没有子类化的直接等价物(尽管嵌入是类似的);您当然可以将结构定义视为类和实例