Golang 访问通用结构的数据元素

标签 go go-interface

我将有一个应用程序,其中包含许多遵循 Req/Rsp 设计的消息。下面实现的是消息 Foo 的单个 Req/Rsp。 Req 将遵循用于处理消息并返回响应的通用接口(interface)。所有 Rsp 消息都将嵌入 MHRSP 结构。我想在 ProcessRequest 方法之外设置响应状态。我遇到的问题是由下面标记为 Problem Area 的代码块导致的运行时错误。
panic: interface conversion: interface {} is *main.FooRsp, not main.MHRSP
由于我将收到许多消息,而不仅仅是 FooRsp,因此转换为 FooRsp 不是解决方案,所以问题是,我如何以通用方式处理这个问题(即能够为任何 Rsp 设置成功和错误消息)?

使用 GDB Online 编译的代码:https://www.onlinegdb.com/online_go_compiler

/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
package main
import (
    "fmt"
    "errors"
    "encoding/json"
)

type MHREQIF interface {
    ProcessRequest(e int) (interface{}, error)
}

type MHRSP struct {
    Success bool `json:"success,omitempty"`
    ErrorMessage string `json:"error_message,omitempty"`
}

type FooReq struct {
    MHREQIF
    Name string `json:"name"`
}

type FooRsp struct {
    MHRSP
    Name string `json:"name"`
}

func (self *FooReq) ProcessRequest(e int) (interface{}, error) {
    rsp := FooRsp{Name:self.Name}
    if 0 == e {
        return &rsp, nil    
    } else {
        return &rsp, errors.New("crap")
    }
}

func main() {
    var msg_req MHREQIF
    msg_req = &FooReq{Name:"bob"}
    rsp, err := msg_req.ProcessRequest(1)
    if err != nil {
        // -------------- PROBLEM AREA BEG ------------------
        v := rsp.(MHRSP)
        v.Success = false
        v.ErrorMessage = fmt.Sprintf("%v", err)
        // -------------- PROBLEM AREA END ------------------
    }
    msg_bytes, _ := json.Marshal(rsp)
    msg_string := string(msg_bytes)
    fmt.Println(msg_string)
}

最佳答案

感谢@mkopriva 和@Adrian 为我指明了正确的方向。有时从 C++ OO 到 go-isms 的转变令人费解:P

这是任何在如何解决此类问题上遇到类似困难的人的工作代码。

/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.
https://www.onlinegdb.com/online_c++_compiler
*******************************************************************************/
package main
import (
    "fmt"
    "errors"
    "encoding/json"
)

type MHREQIF interface {
    ProcessRequest(e int) (MHRESPIF, error)
}

type MHRESPIF interface {
    SetResponse(err error)
}

type MHRSP struct {
    MHRESPIF `json:"-"`
    Success bool `json:"success"`
    ErrorMessage string `json:"error_message,omitempty"`
}

type FooReq struct {
    MHREQIF
    Name string `json:"name"`
}

type FooRsp struct {
    MHRSP
    Name string `json:"name"`
}

func (self *MHRSP) SetResponse(err error) {
    if err != nil {
        self.Success = false
        self.ErrorMessage = fmt.Sprintf("%v", err)
    } else {
        self.Success = true
    }
}

func (self *FooReq) ProcessRequest(e int) (MHRESPIF, error) {
    rsp := FooRsp{Name:self.Name}
    if 0 == e {
        return &rsp, nil    
    } else {
        return &rsp, errors.New("crap")
    }
}

func main() {
    var msg_req MHREQIF
    msg_req = &FooReq{Name:"bob"}
    rsp, err := msg_req.ProcessRequest(1)
    rsp.SetResponse(err)
    msg_bytes, _ := json.Marshal(rsp)
    msg_string := string(msg_bytes)
    fmt.Println(msg_string)
}

关于Golang 访问通用结构的数据元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61918593/

相关文章:

concurrency - 在 RWMutex Unlock 之后两次调用 RWMutex RLock 时 goroutine 阻塞

google-app-engine - 我可以构建一个与本地主机应用引擎数据存储区对话的 golang 命令行工具吗?

go - 如何从 Go 中的结构中的接口(interface)实例获取属性

go - 了解接口(interface)中的接口(interface)(嵌入式接口(interface))

json - 从字节数组创建结构

database - 从数据库获取数据并填充数组的Golang抽象函数

go - 在golang结构中未定义

macos - 如何查找 Mac 文档路径(与语言无关)

go - 如何在 GO 中将 interface{} 转换为 map

google-app-engine - Appengine 搜索语言