英文:
Best practice to use the same function with different structs - Golang
问题
假设我有不同的结构体,它们有共同的字段,我想要为它们使用相同的toString方法,因为逻辑和流程完全相同,我不想重复编写代码。我在思考如何解决这个问题。
type mobile struct {
"version" string,
"appName" string
}
type other struct {
"release" string,
"app_name" string
}
假设我有这两个结构体。实际上,version和release具有相同的含义,mobile的appName和other的app_name也具有相同的含义。
因此,我想编写一个toString
方法,可以列出这两个对象的详细信息。
func detailsOfMobile(app mobile) string {
message := fmt.Sprintf("这是*%s*的详细信息,版本为%s", app.appName, app.version)
.....
return message
}
func detailsOfOther(app other) string {
message := fmt.Sprintf("这是*%s*的详细信息,版本为%s", app.app_name, app.release)
.....
return message
}
实际上,这些方法在实际情况中可能更加复杂。但是我想表达的是,这两个结构体具有共同的字段,但它们的命名不同。在这种情况下,有什么最佳实践可以避免重复代码呢?
英文:
So let's say that I have different structs, which have common fields, and I want to use the same toString method for both.
Because the logic and the flow will be exactly the same. And I don't want to duplicate it. I'm thinking about what can be done about this.
type mobile struct {
"version" string,
"appName" string
}
type other struct {
"release" string,
"app_name" string
}
So let's say I have these two structs. Actually, the version holds the same meaning as the release. And mobile > appName and other> app_name again holds the same meaning.
So I want to write one toString
method where I can list the details of these two objects.
func detailsOfMobile(app mobile) string {
message := fmt.Sprintf("Here is the details of the *%s* with the version %s", app.appName, app.version)
.....
return message
}
so for other I need to duplicate it;
func detailsOfOther (app Ipad) string {
message := fmt.Sprintf("Here is the details of the *%s* with the version %s", app.app_name, app.release)
.....
return message
}
Actually the methods are much more complicated in reality. But what I'm trying to stay here, both structs have common fields, but they are named differently. What can be the best practice here not to duplicate the code?
答案1
得分: 4
你有两种选择,最接近你所要求的方式是使用接口。你的函数接受一个公共接口,而你的结构体都实现了它:
package main
import (
"fmt"
)
type App interface {
Name() string
Version() string
}
type mobile struct {
version string
appName string
}
func (m mobile) Name() string { return m.appName }
func (m mobile) Version() string { return m.version }
type other struct {
release string
app_name string
}
func (o other) Name() string { return o.app_name }
func (o other) Version() string { return o.release }
func detailsOfMobile(a App) string {
message := fmt.Sprintf("这是 *%s* 的详细信息,版本号为 %s", a.Name(), a.Version())
return message
}
func main() {
fmt.Println(detailsOfMobile(mobile{version: "1", appName: "iDaft"}))
fmt.Println(detailsOfMobile(other{release: "2", app_name: "Shazam"}))
}
// 这是 *iDaft* 的详细信息,版本号为 1
// 这是 *Shazam* 的详细信息,版本号为 2
作为一种更简单的方法,你也可以让这两个结构体都实现已知的 Stringer
接口:
package main
import (
"fmt"
)
type mobile struct {
version string
appName string
}
func (m mobile) String() string {
return fmt.Sprintf("%s 版本号 %s", m.appName, m.version)
}
type other struct {
release string
app_name string
}
func (o other) String() string {
return fmt.Sprintf("%s 发布版本 %s", o.app_name, o.release)
}
func main() {
fmt.Println(mobile{version: "1", appName: "iDaft"})
fmt.Println(other{release: "2", app_name: "Shazam"})
}
// iDaft 版本号 1
// Shazam 发布版本 2
英文:
You have two choices, the closest way of doing what you are literally asking is to use an interface. Your function accepts a common interface and your structs both implement it:
package main
import (
"fmt"
)
type App interface {
Name() string
Version() string
}
type mobile struct {
version string
appName string
}
func (m mobile) Name() string { return m.appName }
func (m mobile) Version() string { return m.version }
type other struct {
release string
app_name string
}
func (o other) Name() string { return o.app_name }
func (o other) Version() string { return o.release }
func detailsOfMobile(a App) string {
message := fmt.Sprintf("Here is the details of the *%s* with the version %s", a.Name(), a.Version())
return message
}
func main() {
fmt.Println(detailsOfMobile(mobile{version: "1", appName: "iDaft"}))
fmt.Println(detailsOfMobile(other{release: "2", app_name: "Shazam"}))
}
// Here is the details of the *iDaft* with the version 1
// Here is the details of the *Shazam* with the version 2
As a simpler approach, you could also just make both structs implement the well known Stringer
interface:
package main
import (
"fmt"
)
type mobile struct {
version string
appName string
}
func (m mobile) String() string {
return fmt.Sprintf("%s version %s", m.appName, m.version)
}
type other struct {
release string
app_name string
}
func (o other) String() string {
return fmt.Sprintf("%s release %s", o.app_name, o.release)
}
func main() {
fmt.Println(mobile{version: "1", appName: "iDaft"})
fmt.Println(other{release: "2", app_name: "Shazam"})
}
// iDaft version 1
// Shazam release 2
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论