重新分配一个接口或者允许垃圾回收器在临时变量上完成其工作。

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

Reassign an interface or allow GC to do its work on temporary variables

问题

我对Go语言还很陌生,目前正在将一个PHP程序移植过来。

我知道Go不是一种动态类型语言,我很喜欢这一点。它似乎非常结构化,很容易跟踪一切。

但是我遇到了一些看起来有点...丑陋的情况。有没有更好的方法来执行这种过程:

plyr := builder.matchDetails.plyr[i]
plyrDetails := strings.Split(plyr, ",")
details := map[string]interface{}{
    "position": plyrDetails[0], "id": plyrDetails[1],
    "xStart": plyrDetails[2], "zStart": plyrDetails[3],
}

编辑:

有没有更好的方法来创建一个包含来自plyr的字符串的映射,而不是创建两个额外的变量,然后立即销毁它们?或者这种方式是正确的吗?

英文:

I'm very new to Go and am currently porting a PHP program.

I understand that Go is not a dynamically-typed language and I like that about it. It seems very structured and easy to keep track of everything.

But I've been coming across situations that seem to be a little ... ugly. Is there a better way of performing this sort of process:

plyr := builder.matchDetails.plyr[i]
plyrDetails := strings.Split(plyr, ",")
details := map[string]interface{}{
	"position": plyrDetails[0], "id": plyrDetails[1],
	"xStart": plyrDetails[2], "zStart": plyrDetails[3],
} 

EDIT:

Is there a better way to achieve a map containing the strings from plyr than to create two additional variables, to be destroyed straight afterwards? Or is this the correct way?

答案1

得分: 2

Go不是PHP。用Go编写Go程序,用PHP编写PHP程序。

接口值表示为一个由两个字组成的对,其中一个指向存储在接口中的类型信息的指针,另一个指向相关数据的指针。Go数据结构:接口

重复使用Go接口变量以“提高性能”是没有意义的。

英文:

Go is NOT PHP. Write Go programs in Go. Write PHP programs in PHP.

> Interface values are represented as a two-word pair giving a pointer
> to information about the type stored in the interface and a pointer to
> the associated data. Go Data Structures:
> Interfaces

Reusing Go interface variables to "increase performance" makes no sense.

答案2

得分: 2

如果可能的话,选择一个不同的格式,并让一个库来为你进行字符串解析/生成。
对于你使用多次的任何内容,使用struct而不是map,以获得更多的编译器检查。
常见的使用encoding/json的方式可以同时实现这两个目标。

同时,不要过于担心性能,因为你可能会大大提高旧应用的速度;目前没有迹象表明解析或垃圾回收的速度是一个问题;而你在帖子的第一个版本中提到的语法差异不一定与垃圾回收有关。

所以,我理解你可能正在逐字逐句地移植,这可能限制了你现在可以改变的内容。

但是,如果/当你可以改变事物时,一个非常干净的解决方案是使用encoding/json包和一个结构体:json包将从结构体解析输入/生成输出,而无需你手动进行任何字符串操作,并且使用结构体可以在编译时进行检查,而不仅仅是在运行时进行检查。许多Go应用程序(以及其他应用程序)使用JSON来公开其服务。

一个中间步骤可以是为你至少使用几次的任何内部结构引入struct类型,而不是map,这样即使没有更新解析,至少应用程序的内部可以获得编译时检查的好处。struct也是像the gorm object/relational mapper这样的工具所期望处理的。它们恰好map使用更少的内存,并且访问起来更快(在语法上更简洁),但这甚至不一定是这里最重要的考虑因素。

关于你现在的性能,特别是不同的语法是否会使它更快:不要为此担心,有很多原因:无论你做什么,移植的速度可能都比PHP快;我们还没有任何迹象表明解析或垃圾回收实际上是慢的或者是你的瓶颈;而你在问题的第一个版本中提到的语法差异可能与垃圾回收关系不大,甚至根本没有关系。在你的代码中有更多/更少的变量名可能不一定对应更多/更少的堆分配,因为通常Go可以在堆栈上分配,这在Dave Cheney的Gocon Tokyo幻灯片中简要讨论过'escape analysis'。正如peterSO所说,我们似乎正在查看小引用的分配情况,而不是每次都复制请求中的所有字符串字节。

英文:

tl;dr:

  • If possible, choose a different format and let a library do the string parsing/generation for you
  • Use structs rather than maps for anything you use a few times, for more compiler checks
  • The common way of using encoding/json accomplishes both of those.

Meanwhile, don't sweat perf too much because you'll probably vastly improve the old app's speed regardless; there's no indication speed of parsing or GC is a problem yet; and the syntactical differences you mentioned in the first rev. of the post don't necessarily actually relate to GC.


So, I understand you may be porting piece-for-piece, and that may limit what you can change now.

But if/when you can change things, a really clean solution would be to use the encoding/json package and a struct: the json package will parse input/generate output from structs without any manual string manipulation on your part, and using a struct gives you compile-time checking rather than only the runtime checking you get with a map. Lots of Go apps (and others) use JSON to expose their services.

An intermediate step could be to introduce struct types for any internal structure you use at least a few times, rather than maps, so even without updating the parsing, at least the internals of the app get the benefits of compile-time checking. structs are also what things like the gorm object/relational mapper expect to deal with. They happen to use less memory than maps, and be quicker (and more concise syntactically) to access, but those aren't even necessarily the most important considerations here.

On the performance of what you have now, and particularly whether different syntax would make it faster: don't sweat that, for a bunch of reasons: the port's likely to be faster than the PHP was whatever you do; we don't yet have any indication that parsing or GC is actually slow or your bottleneck; and the syntactical differences you talked about in the first revision of your question may not relate to GC much or at all. More/fewer var names in your code may not correspond to more/fewer heap allocations, 'cause often Go can allocate on the stack, briefly discussed under 'escape analysis' in Dave Cheney's Gocon Tokyo slides. And as peterSO said, we seem to be looking at allocations of smallish references, not, say, copying all of the string bytes from the request each time.

huangapple
  • 本文由 发表于 2014年8月24日 19:06:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/25471047.html
匿名

发表评论

匿名网友

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

确定