Golang中的通用接收器或类似功能探讨
Golang中的通用接收器或类似功能探讨 在一个应用中,我有3个结构体。它们是:
type LoginResponse struct {
ResultResponse
Token string `json:"Token"`
ComercioId string `json:"ComercioId"`
UsuarioId string `json:"UsuarioId"`
}
type DepositoPagoResponse struct {
ResultResponse
TransaccionID int `json:"TransaccionId"`
Producto string `json:"Producto"`
FechaTransaccion time.Time `json:"FechaTransaccion"`
MontoTransaccion float64 `json:"MontoTransaccion"`
}
type VerifyAccountResponse struct {
ResultResponse
Producto string `json:"Producto"`
Saldo float64 `json:"Saldo"`
}
type ResultResponse struct {
IsSuccess bool `json:"IsSuccess"`
Codigo int `json:"Codigo"`
Mensaje string `json:"Mensaje"`
}
为了在我的结构体中设置属性,我编写了一些方法,其工作方式类似于建造者模式。例如:
func (r *VerifyAccountResponse) WithSuccess(success bool) *VerifyAccountResponse {
r.IsSuccess = success
return r
}
func (r *VerifyAccountResponse) WithCodigo(codigo int) *VerifyAccountResponse {
codigo, mensaje := GetCodeMessage(codigo)
r.Codigo = codigo
r.Mensaje = mensaje
return r
}
所以我写了类似这样的代码:
r := &LoginResponse{}
r.WithSuccess(true).WithCode(100).WithToken("123")
等等。WithSuccess 和 WithCode 这些方法在每个结构体中都是重复的。
我希望只为 ResultResponse 编写这些方法一次,然后让每个父结构体都能使用。
我在考虑类似泛型函数接收器之类的东西,以避免为每个父结构体编写这些方法。
这可能吗?如果可以,请提供一些有用的提示……
更多关于Golang中的通用接收器或类似功能探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这不是一个问题,只是想了解如何处理泛型和接收器。
谢谢!!!
更多关于Golang中的通用接收器或类似功能探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这就是我所做的……非常感谢!!!
这样写有什么问题:
r := LoginResponse{
ResultResponse: ResultResponse{
IsSuccess: true,
Codigo: 100,
},
Token: "123",
}
我找到了一个让代码更简洁的方法。首先,我写了一个函数来创建 ResultResponse 对象,然后为其他每个结构体添加一个 WithResultResponse 方法。就像这样:
response.WithResultResponse(models.BuildResultResponse(true, 1097)).
WithToken(“abc123”).
WithUsuarioId(“usuario_1”).
WithComercioId(“9999”)
Go 语言不允许你编写与嵌入式结构体(如 ResultResponse)绑定的泛型构建器方法,因此,如果你想保持链式调用(WithSuccess、WithCodigo 等),就必须为每个父类型重复编写这些方法。为了减少重复,你可以将共享的逻辑移到辅助函数中,然后在每个结构体的构建器方法中调用这些辅助函数。这样更清晰,即使没有完全遵循 DRY 原则。除非你深入研究高级模式,否则泛型或接口在这里帮助不大,而引入高级模式可能不值得增加复杂性。
func main() {
fmt.Println("hello world")
}
在Go中可以通过为嵌入的ResultResponse类型定义方法来实现代码复用。由于你的结构体都嵌入了ResultResponse,可以为ResultResponse定义方法,这些方法会返回*ResultResponse,然后通过类型转换或方法链来使用。
以下是实现方案:
// 为 ResultResponse 定义通用方法
func (r *ResultResponse) WithSuccess(success bool) *ResultResponse {
r.IsSuccess = success
return r
}
func (r *ResultResponse) WithCodigo(codigo int) *ResultResponse {
codigo, mensaje := GetCodeMessage(codigo)
r.Codigo = codigo
r.Mensaje = mensaje
return r
}
// 使用示例
func main() {
// 方法1:直接操作嵌入的ResultResponse
loginResp := &LoginResponse{}
loginResp.ResultResponse.WithSuccess(true).WithCodigo(100)
loginResp.Token = "123"
// 方法2:创建辅助函数来链式调用
depositResp := &DepositoPagoResponse{}
depositResp.WithResult(true, 100).Producto = "Producto1"
}
// 辅助函数示例
func (r *LoginResponse) WithResult(success bool, codigo int) *LoginResponse {
r.ResultResponse.WithSuccess(success).WithCodigo(codigo)
return r
}
func (r *DepositoPagoResponse) WithResult(success bool, codigo int) *DepositoPagoResponse {
r.ResultResponse.WithSuccess(success).WithCodigo(codigo)
return r
}
如果需要保持完全相同的链式调用语法,可以使用接口和类型断言:
type ResultBuilder interface {
WithSuccess(bool) ResultBuilder
WithCodigo(int) ResultBuilder
}
// 确保所有响应类型都实现ResultBuilder
var _ ResultBuilder = (*LoginResponse)(nil)
var _ ResultBuilder = (*DepositoPagoResponse)(nil)
func (r *LoginResponse) WithSuccess(success bool) ResultBuilder {
r.ResultResponse.WithSuccess(success)
return r
}
func (r *LoginResponse) WithCodigo(codigo int) ResultBuilder {
r.ResultResponse.WithCodigo(codigo)
return r
}
// 其他结构体实现类似
或者使用泛型(Go 1.18+):
type Response[T any] struct {
ResultResponse
Data T
}
func (r *Response[T]) WithSuccess(success bool) *Response[T] {
r.ResultResponse.WithSuccess(success)
return r
}
func (r *Response[T]) WithCodigo(codigo int) *Response[T] {
r.ResultResponse.WithCodigo(codigo)
return r
}
// 使用
type LoginData struct {
Token string `json:"Token"`
ComercioId string `json:"ComercioId"`
UsuarioId string `json:"UsuarioId"`
}
resp := &Response[LoginData]{}
resp.WithSuccess(true).WithCodigo(100)
resp.Data.Token = "123"
最直接的方案是第一种:直接为ResultResponse定义方法,然后通过嵌入结构体来访问这些方法。这样只需要维护ResultResponse的方法,所有嵌入它的结构体都能使用。

