在golang中使用for循环反转字符串是否效率低下?

在golang中使用for循环反转字符串是否效率低下?,go,Go,我是这样做的,戈朗: func reverseStr(str string) string { var reversed string for i := len(str) - 1; i >= 0; i-- { reversed += string(str[i]) } return reversed } 我是个初学者,目前还不能做得更好,但我还在学习。我想知道我的方法是否比我在网上看到的那些使用符文的方法效率低: func reverse

我是这样做的,戈朗:

func reverseStr(str string) string {
    var reversed string

    for i := len(str) - 1; i >= 0; i-- {
        reversed += string(str[i])
    }

    return reversed
}
我是个初学者,目前还不能做得更好,但我还在学习。我想知道我的方法是否比我在网上看到的那些使用符文的方法效率低:

func reverse(s string) string {
    chars := []rune(s)
    for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
        chars[i], chars[j] = chars[j], chars[i]
    }
    return string(chars)
}
func反向(s字符串)字符串{
字符:=[]符文
对于i,j:=0,len(chars)-1;i
我想知道我的方法是否比我在网上看到的那些使用符文的方法效率低

与符文或循环的
无关。您的方法一次又一次地构建、重建、重建字符串。而另一个则通过简单地交换字符来反转字符串。更大的字符串只会使差异变得更大

package main

import "testing"

func reverseConcat(str string) string {
    var reversed string

    for i := len(str) - 1; i >= 0; i-- {
        reversed += string(str[i])
    }

    return reversed
}

func reverseSwapRunes(s string) string {
    chars := []rune(s)
    for i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {
        chars[i], chars[j] = chars[j], chars[i]
    }
    return string(chars)
}

func BenchmarkConcatSmall(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseConcat("hello world")
    }
}

func BenchmarkSwapRunesSmall(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseSwapRunes("hello world")
    }
}

func BenchmarkConcatLarger(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseConcat("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
    }
}

func BenchmarkSwapRunesLarger(b *testing.B) {
    for i := 0; i < b.N; i++ {
        reverseSwapRunes("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")
    }
}

您的第一个解决方案只适用于ASCII字符,因为len(str)以字节为单位提供len,str[i]也返回byte。一旦开始处理Unicode,它就会失败,因为一个Unicode(符文)可以有多个字节

type byte = uint8
type rune = int32
因此,您的第二个解决方案将适用于任何类型的字符串

另一个例子是使用strings.Builder

func Reverse(in string) string {
    var sb strings.Builder
    runes := []rune(in)
    for i := len(runes) - 1; 0 <= i; i-- {
        sb.WriteRune(runes[i])
    }
    return sb.String()
}

如果不知道“我在网上看到的那些”是什么,就不可能说这是否更有效,但考虑到它是在字节而不是符文上运行的,它不兼容UTF(它会破坏任何多字节字符)。我不关心多字节字符。这两种方法都使用
for
循环:耸耸肩:在这种情况下,不清楚问题是什么(至少是标题)。带有for循环的代码可能非常有效。或者不是。取决于你在循环中放了什么。当你想知道这两种方法中哪一种更有效时,带交换符文的方法似乎是次线性扩展的。有趣。如果你知道(或有一个估计)最终大小,你应该预先分配构建者:
sb.Grow(len(in))
func Reverse(in string) string {
    var sb strings.Builder
    runes := []rune(in)
    for i := len(runes) - 1; 0 <= i; i-- {
        sb.WriteRune(runes[i])
    }
    return sb.String()
}
BenchmarkReverseStrConcat-8    1000000  1571 ns/op  176 B/op    29 allocs/op     
BenchmarkReverseStrBuilder-8   3000000  499 ns/op   56 B/op 6 allocs/op