英文:
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
struct
s rather thanmap
s 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 map
s, so even without updating the parsing, at least the internals of the app get the benefits of compile-time checking. struct
s 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论