Best practice to use the same function with different structs – Golang

huangapple go评论84阅读模式
英文:

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

huangapple
  • 本文由 发表于 2021年9月30日 22:11:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/69393728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定