Go 通过数组+;从值创建字符串
有了这段代码,是否有更好的方法循环遍历所有用户并创建一个包含所有用户Go 通过数组+;从值创建字符串,go,Go,有了这段代码,是否有更好的方法循环遍历所有用户并创建一个包含所有用户Nick值的新字符串 package main import "fmt" type User struct { Nick string } func main() { var users [2]User users[0] = User{ Nick: "Radar" } users[1] = User{ Nick: "NotRadar" } names := ":"
Nick
值的新字符串
package main
import "fmt"
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{ Nick: "Radar" }
users[1] = User{ Nick: "NotRadar" }
names := ":"
for _, u := range users {
names += u.Nick + " "
}
fmt.Println(names)
}
比如说,
package main
import (
"bytes"
"fmt"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
var buf bytes.Buffer
buf.WriteByte(':')
for _, u := range users {
buf.WriteString(u.Nick)
buf.WriteByte(' ')
}
names := buf.String()
fmt.Println(names)
}
这避免了由于串接string
s而导致的大量分配
你也可以写:
package main
import (
"fmt"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
var buf []byte
buf = append(buf, ':')
for _, u := range users {
buf = append(buf, u.Nick...)
buf = append(buf, ' ')
}
names := string(buf)
fmt.Println(names)
}
看起来你真的想在这里吃点东西。您可能希望避免原始代码中重复字符串连接的紧密循环;我相当肯定Go没有为它的原始字符串实现数据结构
package main
import (
"fmt"
"strings"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
userNames := []string{}
for _, u := range users {
userNames = append(userNames, u.Nick)
}
names := ":" + strings.Join(userNames, " ")
fmt.Println(names)
}
不幸的是,我不知道有什么更优雅的方式来编写代码 Go确实有一个方法,因此如果您制作了一个帮助器,将您的用户数组转换为字符串片段(
[]string
),那么您可以将其传递到string.Join
)
我认为Go的静态类型和缺少模板使得它很难像Ruby那样编写通用的
map
函数。有效地重写联接,以防止必须在列表上迭代额外的时间并分配额外的切片
func Usernames(users []User) string {
if len(users) == 0 {
return ""
}
if len(users) == 1 {
return users[0].Name
}
sep := " "
n := len(users)-1 // From len(sep) * len(a)-1, sep is always len 1 unlike in Join
for i := 0; i < len(users); i++ {
n += len(users[i].Name)
}
names := make([]byte,n)
namesp := copy(names, users[0].Name)
for _,u := range users[1:] {
namesp += copy(names[namesp:], sep)
namesp += copy(names[namesp:], u.Name)
}
return string(names)
}
func用户名(users[]User)字符串{
如果len(用户)==0{
返回“”
}
如果len(用户)==1{
返回用户[0]。名称
}
九月:=“”
n:=len(users)-1//From len(sep)*len(a)-1,sep与Join中的len 1不同
对于i:=0;i
作为参考,strings.go与strings一起。连接源:
请参见第356行您对这种方法有什么问题?这对我来说似乎很标准(也许你想在某些情况下使用strings.TrimSpace(names)或names[:len(names)-1]来去掉多余的尾随空间)。好吧,我是一名Ruby程序员,在Ruby中我只需要做
users.map(&:name).join(“”)
。我想围棋中可能有一些明显的东西我错过了。啊,是的。我应该考虑一下。好主意:)使用字符串。连接在这里是多余的。如果您查看Join的源代码,它基本上是问题中示例代码的一个更奇特的变体,但它使用内置的copy()函数,而不是与“+=”串联。实际上,你只是在用strings.Join加倍你的工作。至少,如果要这样做,您应该将用户名:=[]字符串{}替换为用户名:=make([]字符串,0,len(用户)),否则“append”与“+=”处理字符串时遇到的问题相同。不,这实际上是不同的<代码>字符串。Join对一个字符串进行单个分配,分配的字符串大小等于所有已连接字符串的组合大小(的第364-366行)。与重复分配越来越大的字符串相比,这种方法的效率要大得多。想想“高斯和”,你就会明白其中的根本原因。关于声明用户名容量的说明很好,但是append()在如何基于著名的动态数组扩展算法进行扩展方面更聪明。@Jsor:你能用你所说的代码来回答这个问题,以便我能理解吗?我应该补充一点,peterSO的回答也非常正确:它避免了重复串接的相同陷阱,而且比我的解决方案更灵活。我们最好合并这两个答案。我建议避免使用字符串的内联。加入,除非探查器告诉我们这对我们有很大帮助。没有测量或数据支持的优化可能会出错。不使用标准库意味着错过了对这些库未来的任何改进。