Golang中如何从一个结构体方法访问另一个结构体的方法

Golang中如何从一个结构体方法访问另一个结构体的方法 你好,

我希望从一个结构体的方法(Operator.OperateThis/OperateThat)内部访问另一个结构体的方法(Service.DoThis/DoThat)。通过将 Service 注入到 Operator 中可以轻松实现,这也是我目前的做法,但我想避免这样做——请参考下面的简单示例。我只是不想在 Operator 中看到 Service 结构体。这可能吗?如果可以,最优雅/最简洁的方法是什么?

理想情况下,我不想向 Operator 中注入任何东西。但是,我可以接受注入除 Service 之外的任何东西。我研究过将变量/类型作为函数,但没有进展。这里的关键点是,Service 只被实例化一次,我想保留它的引用。

谢谢

main.go

package main

import "log"

func main() {
	operator := &Operator{}
	StartService(operator)

	if err := operator.OperateThis(); err != nil {
		log.Fatalln(err)
	}

	if err := operator.OperateThat(); err != nil {
		log.Fatalln(err)
	}
}

connection.go

package main

type Connection struct {
	// ...
}
// ...

service.go

package main

type Service struct {
	connection *Connection
	// ...
}

func StartService(operator *Operator) {
	// ...
	operator.SetService(&Service{})
	// ...
}

func (s *Service) DoThis() error {
	s.obtainConnection()
	// ...
	return nil
}

func (s *Service) DoThat() error {
	s.obtainConnection()
	// ...
	return nil
}

// ...

func (s *Service) obtainConnection() {
	s.connection = &Connection{}
}

operator.go

package main

import "log"

type Operator struct {
	service *Service
}

func (o *Operator) SetService(service *Service) {
	o.service = service
}

func (o *Operator) OperateThis() error {
	if err := o.service.DoThis(); err != nil {
		log.Fatalln(err)
	}

	log.Println("operated this")
	return nil
}

func (o *Operator) OperateThat() error {
	if err := o.service.DoThat(); err != nil {
		log.Fatalln(err)
	}

	log.Println("operated that")
	return nil
}

更多关于Golang中如何从一个结构体方法访问另一个结构体的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

另一件事是这些结构体紧密耦合。Service 知道 operator,而 operator 也知道 Service。我认为这是你问题的根源。

实际上,这正是我试图通过找到一个令人愉快的解决方案来摆脱的 😊

不过,你的例子仍然将 Service 注入到了 Operator 中,而这正是我想要避免的。

更多关于Golang中如何从一个结构体方法访问另一个结构体的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果你通过函数来改变结构体的字段,可以使用接口来隐藏你想要隐藏的部分。

type Operator interface {
    OperateThis() error
    OperateThat() error
}
type Service struct {
	operator Operator
	// ...
}

func StartService(operator Operator) {
	// ...
	operator.SetService(&Service{})
	// ...
}

另一个问题是这些结构体之间的耦合非常紧密。Service 知道 operator,而 operator 也知道 Service。我认为这是你遇到问题的根本原因。

可以通过接口来解耦,这样Operator就不需要直接依赖Service结构体。定义一个Service接口,然后让Operator持有该接口类型:

package main

import "log"

// 定义Service接口
type Service interface {
    DoThis() error
    DoThat() error
}

type Operator struct {
    service Service  // 改为接口类型
}

func (o *Operator) SetService(service Service) {
    o.service = service
}

func (o *Operator) OperateThis() error {
    if err := o.service.DoThis(); err != nil {
        log.Fatalln(err)
    }
    log.Println("operated this")
    return nil
}

func (o *Operator) OperateThat() error {
    if err := o.service.DoThat(); err != nil {
        log.Fatalln(err)
    }
    log.Println("operated that")
    return nil
}

Service结构体实现该接口:

package main

type ServiceImpl struct {
    connection *Connection
}

func (s *ServiceImpl) DoThis() error {
    s.obtainConnection()
    // ...
    return nil
}

func (s *ServiceImpl) DoThat() error {
    s.obtainConnection()
    // ...
    return nil
}

func (s *ServiceImpl) obtainConnection() {
    s.connection = &Connection{}
}

修改StartService函数:

func StartService(operator *Operator) {
    operator.SetService(&ServiceImpl{})
}

这样Operator只依赖Service接口,不依赖具体的ServiceImpl结构体。如果需要进一步解耦,可以使用函数类型:

package main

import "log"

type Operator struct {
    doThisFunc func() error
    doThatFunc func() error
}

func (o *Operator) SetOperations(doThis, doThat func() error) {
    o.doThisFunc = doThis
    o.doThatFunc = doThat
}

func (o *Operator) OperateThis() error {
    if err := o.doThisFunc(); err != nil {
        log.Fatalln(err)
    }
    log.Println("operated this")
    return nil
}

func (o *Operator) OperateThat() error {
    if err := o.doThatFunc(); err != nil {
        log.Fatalln(err)
    }
    log.Println("operated that")
    return nil
}

初始化时注入函数:

func StartService(operator *Operator) {
    service := &Service{}
    operator.SetOperations(service.DoThis, service.DoThat)
}
回到顶部