英文:
Avoid code duplication with interface in golang
问题
避免这种代码重复的惯用方法是使用接口和泛型。你可以创建一个通用的创建方法,接受一个接口类型作为参数,然后在方法内部使用类型断言来处理不同的对象。这样可以避免重复的代码。
以下是一个示例:
func Create(ctx context.Context, obj interface{}) (interface{}, error) {
switch v := obj.(type) {
case *Account:
if ret, err := datastore.Put(ctx, v.newKey(ctx), v); err != nil {
log.Errorf(ctx, "Error while creating Account: %v\n", err)
return nil, err
} else {
v.Id = strconv.FormatInt(ret.IntID(), 10)
}
return v, nil
case *Index:
if ret, err := datastore.Put(ctx, v.newKey(ctx), v); err != nil {
log.Errorf(ctx, "Error while creating Index: %v\n", err)
return nil, err
} else {
v.Id = strconv.FormatInt(ret.IntID(), 10)
}
return v, nil
default:
return nil, errors.New("Unsupported type")
}
}
通过将对象作为接口类型传递给通用的创建方法,你可以避免重复的代码,并根据对象的类型执行相应的操作。这样,你只需要编写一次创建方法,就可以处理不同类型的对象。
英文:
I am using the Google Cloud Datastore (or the google app engine datastore), to store different objects. Most of these objects are similar, hence I end up with lots of code duplication.
As an example, here are two create methods, of two different objects, account
and index
.
func (account *Account) Create(ctx context.Context) (*Account, error) {
if ret, err := datastore.Put(ctx, account.newKey(ctx), account); err != nil {
log.Errorf(ctx, "Error while creating Account : %v\n", err)
return nil, err
} else {
account.Id = strconv.FormatInt(ret.IntID(), 10)
}
return account, nil
}
func (index *Index) Create(ctx context.Context) (*Index, error) {
if ret, err := datastore.Put(ctx, index.newKey(ctx), index); err != nil {
log.Errorf(ctx, "Error while creating Index : %v\n", err)
return nil, err
} else {
index.Id = strconv.FormatInt(ret.IntID(), 10)
}
return index, nil
}
As you can see, the two snippets are identical, excepts for the holder type, the return type, and the error message.
What is the idiomatic way to avoid this kind of code duplication ?
答案1
得分: 3
使用接口定义方法NewKey()
和SetID()
type Entity interface {
SetId(id int64)
NewKey(c context.Context) *datastore.Key
}
func create(c context.Context, entity Entity) error {
if ret, err := datastore.Put(c, entity.NewKey(c), entity ); err != nil {
log.Errorf(c, "Error while creating entity: %v\n", err)
return err
} else {
entity.SetId(ret.IntID())
return nil
}
}
func (index *Index) Create(c context.Context) (*Index, error) {
return index, create(c, index)
}
func (account *Account) Create(c context.Context) (*Account, error) {
return account, create(c, account)
}
英文:
Use interface to define methods NewKey()
& SetID()
type Entity interface {
SetId(id int64)
NewKey(c context.Context) *datastore.Key
}
func create(c context.Context, entity Entity) error {
if ret, err := datastore.Put(c, entity.NewKey(c), entity ); err != nil {
log.Errorf(c, "Error while creating entity: %v\n", err)
return err
} else {
entity.SetId(ret.IntID())
return nil
}
}
func (index *Index) Create(c context.Context) (*Index, error) {
return index, create(c, index)
}
func (account *Account) Create(c context.Context) (*Account, error) {
return account, create(c, account)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论