我正在使用GraphQL和go-pg

我有很多这样的实体:

type Player struct {
    ID        int
    CreatedAt time.Time `pg:"default:now(),notnull"`
    TeamID    int `pg:",notnull"`
    Team      *Team
    Type      int
    Score     int64 `pg:",notnull"`
    Note      *string
    // and others...
}

type PlayerInput struct {
    TeamID  int
    Type    int
    Score   int64
    Note    *string
    // and others...
}

我有很多类似的功能:

func (db *postgres) Update(context context.Context, id int, input types.PlayerInput) (*types.Player, error) {

    var actualPlayer types.Player

    newPlayer := graphqlToDB(&input)

    tx, err := db.Begin()
    //handle err

    err = tx.Model(&actualPlayer).Where("id = ?", id).For("UPDATE").Select()
    // handle err and rollback

    actualPlayer.TeamID = newPlayer.TeamID
    actualPlayer.Type = newPlayer.Type
    actualPlayer.Score = newPlayer.Score
    actualPlayer.Note = newPlayer.Note
    // and others...

    _, err = tx.Model(&actualPlayer).WherePK().Update()
    // handle err and rollback

    err = tx.Commit()
    //handle err

    return &actualPlayer, nil
}

func graphqlToDB(input *types.PlayerInput) *types.Player {

    var output = &types.Player{
        TeamID:   input.TeamID,
        Type:     input.Type,
        Score:    input.Score,
        Note:     input.Note,
        // and others...
    }

    if input.Type == "example" {
        output.Score = 10000000
  }

    return output
}

我为项目中的每个实体都有此代码,我想限制/避免冗余代码,特别是:

每次从Graphql输入类型转换


  • newPlayer := graphqlToDB(&input)
    
  • 每次都手动更新这些(和其他)字段

    actualPlayer.TeamID = newPlayer.TeamID
    actualPlayer.Type = newPlayer.Type
    actualPlayer.Score = newPlayer.Score
    actualPlayer.Note = newPlayer.Note
    
  • 每次打开和关闭数据库事务

    tx, err := db.Begin()
    

  • 我要月亮吗?

    最佳答案

    我认为这段代码中没有多余的冗余。

    每次时从Graphql输入类型转换



  • 将结构从外部模型转换为内部模型是一种常见的模式,有助于分离关注点。此外,您已经拥有graphqlToDB函数,该函数可让您在其主体中重用10行代码。那可能是最好的。
  • 每次
  • 时手动更新这些(和其他)字段

    在此处显示的特定代码段中,actualPlayer的类型为types.Player,并且graphqlToDB函数返回*types.Player对象。
    因此,您可以简单地编写actualPlayer := graphqlToDB(&input),然后像tx.Model(actualPlayer)一样传递指针。
    这将重新映射newPlayer保存为actualPlayer
  • 每次
  • 都会打开和关闭数据库事务

    如果需要每次以事务方式访问数据库,则需要每次都打开事务(然后提交/回滚)。这是没有多余的。重构可能会导致可读性下降。

    08-03 12:56