如何在Go语言中使用清晰的结构值来优化性能?

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

How to optimize performance with clear struct value in Go?

问题

你好!根据你的代码,你可以通过将p.Cards设置为nil来清空结构体对象中的Cards元素。这样做是可以的,因为在下一次请求到达时,json.Unmarshal将会重新填充p.Cards。这种方法是有效的,但如果你想要更加严谨和清晰的代码,你可以使用p.Cards = []Card{}来清空Cards元素,这样可以确保p.Cards是一个空的切片,而不是nil

至于你的数据库操作,代码中的事务处理和插入语句看起来是正确的。不过,你需要确保数据库连接和事务的创建是正确的,并且在适当的时候进行提交或回滚。另外,你可能需要处理一些错误情况,比如在执行插入语句时出现错误时进行回滚操作。这样可以确保数据的一致性和完整性。

英文:

My API server accept post request and the request body is JSON,so I create two struct object to accept JSON string and persist it into database.But everytime I accept a request I need create the struct object over and over again,I try to clear the struct instead of recreate it.And the demo code like this following:

//The two struct
type Card struct {
  Number string
  Type   string
}

type Person struct {
  Name string
  Cards []Card
}

var p Person

//parse JSON to the struct object
func init() {
  str := `{"name":"aaa","cards":[{"number":"1","type":"visa"},{"number":"2","type":"mastercard"}]}`
  json.Unmarshal([]byte(str), &p)
}

func PersistToDatabase() {
  var err error
  tx, err := db.Begin()
  if err != nil {
    return
  }
  
  defer func() {
    if err != nil && tx != nil {
      if err := tx.Rollback(); err != nil {
        return
      }
    }
  }

  finish := make(chan bool)

  stmt1, err := tx.Prepare(`insert into tb1(name) values(?)`)
  if err != nil {
    panic(err.Error())
  }
  defer stmt1.Close()

  stmt2, err := tx.Prepare(`insert into tb2(name, num, type) values(?, ?, ?)`)
  if err != nil {
    panic(err.Error())
  }
  defer stmt2.Close()

  go func() {
    defer func() { finish <- true }()
    if _, err = stmt1.Exec(p.name); err != nil {
      log.Println("stmt1.Exec: ", err.Error())
      return
    }
   
    for _, x := range p.Cards {
      if _, err = stmt2.Exec(p.name, x.Number, x.Type); err != nil {
        log.Println("stmt2.Exec: ", err.Error())
          return
      }
    }
  }
  <-finish
  //clear struct object
  p.Name = ""
  p.Cards = nil //have anything do this better?
}

In the code bottom I clear the Name element but let the Cards element to be nil,how can I do better? And do my databases operation have any problem?

答案1

得分: 6

一个结构体不是一个对象[1]。虽然从根本上说它们都是以某种方式组织的有序数据,但结构体实际上只是一组变量的列表。不会调用构造函数。除了成员元素的内存之外,不会分配任何额外的内存,也不会在任何特殊的位置分配。 (尽管在大多数面向对象的语言中,这可能并不太昂贵,优化器有时候很厉害)如果我有

type A struct {
    I int
    S string
}

var MyA A

它与下面的代码实际上没有太大区别

var (
    I int
    S string
)

写一个类型MyA = A{}的零值结构体实际上等同于执行MyA.I = 0; MyA.S = "",而这又等同于执行I = 0; S = ""。执行上述任何操作都不会有(显著的)性能开销。

这并不意味着结构体没有用处。它们在概念上非常有用,可以用于定义方法,用于填充数据,比如在处理JSON时。但它们并没有显著的区别。最后,这是最重要的一点,在这段代码中,你有进行过性能分析,发现有显著的性能瓶颈吗?如果没有(我猜应该没有),不用担心,应该没问题的。 如何在Go语言中使用清晰的结构值来优化性能?

[1] Java或C#风格的对象,在理论上(即使在实践中不是)更昂贵。不同于C++对象,它们更像Go的结构体。

英文:

A struct is not an object[1]. While fundamentally they're both mishmashes of ordered data in some way or another, a struct is effectively just a list of variables. No constructor is called. No memory beyond that of its member elements is allocated, and it's not allocated in any special place. (Granted this probably isn't too expensive even in most OO languages, optimizers are pretty cool sometimes) If I have

type A struct {
    I int
    S string
}

var MyA A

It's not really substantially different from

var (
    I int
    S string
)

Writing the zero struct of a type MyA = A{} is effectively equivalent to doing MyA.I = 0; MyA.S = "" which is, in turn, effectively equivalent to I = 0; S = "". There should be no (significant) performance overhead doing any of the above.

This doesn't mean structs aren't useful. They're exceptionally useful, conceptually, for defining methods on, for filling in data such as in cases like JSON. But what they're not is significantly different. Finally, and this is the most important thing, is there a significant performance bottleneck you have profiled in this block of code? If not (and I suspect not), don't worry about it, it's probably fine. 如何在Go语言中使用清晰的结构值来优化性能?

[1] Java or C#-style object, which are theoretically (even if not in practice) more expensive. Not C++ objects which are different (and more like Go structs).

huangapple
  • 本文由 发表于 2014年3月5日 10:44:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/22187450.html
匿名

发表评论

匿名网友

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

确定