How can we reverse a simple string in Go?
-
2As far as I understand, the solutions given below don't work with precomposed or combining characters, like giving `a+´` instead of `á`. I wonder how that could be taken into account, without normalizing it. – siritinga Sep 05 '14 at 07:55
-
If you are confused with a huge number of similar answers, [check my benchmark](http://stackoverflow.com/a/34521190/1090562). – Salvador Dali Dec 30 '15 at 00:22
-
2For strings which are *not* simple, see https://stackoverflow.com/a/62743214/6309 – VonC Dec 15 '20 at 16:34
-
3Seems like something apparently so hard should be in the standard library...but just another thing left out. – Benny Jobigan Apr 01 '21 at 14:59
-
as @dolmen noted many answers are not that great. I suggest the reader to check for https://stackoverflow.com/questions/53244824/how-to-manipulate-strings-in-go-to-reverse-them/62743214#62743214 I also vote to close that question as dup. Not great for search engines, but correctness seems more important (that last pst can also be renamed). – Sep 21 '21 at 21:45
-
Does this answer your question? [How to manipulate strings in GO to reverse them?](https://stackoverflow.com/questions/53244824/how-to-manipulate-strings-in-go-to-reverse-them) – Sep 21 '21 at 21:45
35 Answers
In Go1 rune is a builtin type.
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}

- 4,462
- 1
- 20
- 14
-
6you cannot use len() in Go to find out the length of a string/Array/Slice etc... Here's why? - len() in Go means the size of the input in bytes. It does not correspond to its length. - Not all utf8's runes are of the same size. It can be either 1, 2, 4, or 8. - You should use unicode/ut8 package's method RuneCountInString to get the length of the rune. – Anvesh Checka May 25 '14 at 15:17
-
35@AnveshChecka, that is incorrect. See http://golang.org/pkg/builtin/#len - len() on a slice definitely returns the number of elements, not the size in bytes. A slice of runes is the correct way to do it. – chowey Jan 17 '15 at 02:53
-
9@рытфолд This does not work with combining characters. See http://play.golang.org/p/sBgZAV7gCb, the combining character is not swapped with its base. – chowey Jan 17 '15 at 02:59
Russ Cox, on the golang-nuts mailing list, suggests
package main
import "fmt"
func main() {
input := "The quick brown 狐 jumped over the lazy 犬"
// Get Unicode code points.
n := 0
rune := make([]rune, len(input))
for _, r := range input {
rune[n] = r
n++
}
rune = rune[0:n]
// Reverse
for i := 0; i < n/2; i++ {
rune[i], rune[n-1-i] = rune[n-1-i], rune[i]
}
// Convert back to UTF-8.
output := string(rune)
fmt.Println(output)
}

- 30,132
- 47
- 125
- 187
-
26
-
20
-
2Wow, wtf is up with the double assignment when reversing? Interesting. Now, think about a string with an uneven number of runes. The middle one gets special treatment, with the correct end-result after all though. :) An interesting little optimization I wouldn’t have thought of right away. – Kissaki Jul 15 '12 at 21:36
-
5I don't understand why this conversion to rune, why not `rune:=[]rune(input)`? – siritinga Sep 05 '14 at 07:31
-
1You don't need the first for range loop. output := []rune(input); n := len(output) And you don't need the rune=rune[0:n] – dvallejo Aug 03 '15 at 17:10
-
I agree @dvallejo, see http://play.golang.org/p/S2NIvT_DJ6 the first loop is not usefull and there is no reason to build rune=rune[0:n] – Metal3d Nov 22 '15 at 12:09
-
One more wrong "solution" that doesn't handle combining characters properly. – dolmen Jul 26 '16 at 12:41
-
Doesn't work with combining characters for eg: "The quick bròwn 狐 jumped over the lazy 犬" – Jan 10 '18 at 05:25
-
1@dolmen: Point taken, but to his credit, Russ notes in the mailing list post that his solution ignores combining characters. – Kostas Jun 21 '18 at 11:45
-
What's the purpose of setting `rune` to be a slice of itself in this line: `rune = rune[0:n]`. It seems like this is redundant. – N4v Sep 10 '18 at 21:53
-
2@N4v: With this solution, `rune` is initialized to `len(input)`, which is the number of bytes in input. But a rune can be 1, 2, 4 or 8 bytes in UTF-8. So if all the runes are 1 byte (ASCII) UTF-8 characters, the number of runes in `input` will be equal to the number of bytes. But if some characters are longer byte sequences, then the number of runes will be less than the number of bytes. `rune = rune[0:n]` trims excess 0-valued runes from the end of the slice, which would then be included in the reverse loop and wind up on the front of the `output` string. – Jason Carlson Jul 18 '19 at 21:00
-
-
Sadly, `2️⃣` doesn't work with this function. It returns as `⃣️2`. https://paiza.io/projects/8ZJ759tmsuDiQJfwWk5HsA – KEINOS Oct 16 '20 at 04:24
-
Does overwriting the built-in `rune` serve a purpose? I'm new to Go and I'd have assumed that'd be considered "bad practice". – mathandy Oct 20 '21 at 00:31
This works, without all the mucking about with functions:
func Reverse(s string) (result string) {
for _,v := range s {
result = string(v) + result
}
return
}

- 589
- 4
- 2
-
11While it works, since strings are immutable, it's very inefficient. I've posted a more efficient solution. – peterSO Feb 11 '11 at 07:16
-
7This is *much* too easy to understand. Make it harder :-) (and, "plus one" for just getting on with it) – Roboprog Apr 13 '13 at 01:33
-
3
-
1One more wrong "solution" that doesn't handle combining characters properly. – dolmen Jul 26 '16 at 12:42
-
1@dolmen - why would this not handle combining characters? a range on a string returns a rune which is a codepoint. – Stan R. Mar 09 '17 at 18:06
-
4@StanR. A rune is not a glyph. A glyph can be made of multiple codepoints/runes. See http://reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks Reversing codepoints will attach combining marks to a different base code point. – dolmen Mar 16 '17 at 23:14
-
1
-
O(n^2) complexity, where n is the length of the input string. Poor performance for long strings. – jub0bs Dec 14 '22 at 06:58
From Go example projects: golang/example/stringutil/reverse.go, by Andrew Gerrand
/*
Copyright 2014 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Reverse returns its argument string reversed rune-wise left to right.
func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
Go Playground for reverse a string
After reversing string "bròwn", the correct result should be "nwòrb", not "nẁorb".
Note the grave above the letter o.
For preserving Unicode combining characters such as "as⃝df̅" with reverse result "f̅ds⃝a",
please refer to another code listed below:

- 1,403
- 1
- 18
- 28
-
2Thanks for clarifying the difference from http://stackoverflow.com/a/10030772/3093387 -- it seems that these two solutions differ in how they handle strings like "bròwn". – josliber Jan 11 '16 at 19:21
-
2Thanks for mentioning the Rosettacode solution that handles combining characters – dolmen Jul 26 '16 at 12:56
-
There are too many answers here. Some of them are clear duplicates. But even from the left one, it is hard to select the best solution.
So I went through the answers, thrown away the one that does not work for unicode and also removed duplicates. I benchmarked the survivors to find the fastest. So here are the results with attribution (if you notice the answers that I missed, but worth adding, feel free to modify the benchmark):
Benchmark_rmuller-4 100000 19246 ns/op
Benchmark_peterSO-4 50000 28068 ns/op
Benchmark_russ-4 50000 30007 ns/op
Benchmark_ivan-4 50000 33694 ns/op
Benchmark_yazu-4 50000 33372 ns/op
Benchmark_yuku-4 50000 37556 ns/op
Benchmark_simon-4 3000 426201 ns/op
So here is the fastest method by rmuller:
func Reverse(s string) string {
size := len(s)
buf := make([]byte, size)
for start := 0; start < size; {
r, n := utf8.DecodeRuneInString(s[start:])
start += n
utf8.EncodeRune(buf[size-start:], r)
}
return string(buf)
}
For some reason I can't add a benchmark, so you can copy it from PlayGround (you can't run tests there). Rename it and run go test -bench=.

- 1
- 1

- 214,103
- 147
- 703
- 753
-
2None of those "solutions" handles [combining marks](http://reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks) correctly. – dolmen Mar 16 '17 at 23:21
-
This one panics when put into a fuzz test. See here what I used https://go.dev/play/p/lwhpL5Geo50 – Philipp Pixel Jun 22 '23 at 13:00
This works on unicode strings by considering 2 things:
- range works on string by enumerating unicode characters
- string can be constructed from int slices where each element is a unicode character.
So here it goes:
func reverse(s string) string {
o := make([]int, utf8.RuneCountInString(s));
i := len(o);
for _, c := range s {
i--;
o[i] = c;
}
return string(o);
}

- 71,383
- 57
- 178
- 228
-
I would assign `i:=len(o)-1` and then fold the for into a single line `for _, c:=range s { o[i--]=c; }`. Man I HATE the for without parentheses - is this allowed: `for(_, c:=range s) { o[i--]=c; }` – Lawrence Dol Nov 19 '09 at 19:43
-
-
7@Software_Monkey: o[i--] = c is not allowed in Go. -- and ++ are statements, not expressions. _ means to discard (ignore) that variable. – Randy Sugianto 'Yuku' Nov 25 '09 at 07:10
-
3with go 1.1+ it returns error in string([]int) line, if instead []rune type is used for o, all works – Otuk Aug 11 '13 at 03:37
-
2
-
On go 1.20: `cannot use c (variable of type rune) as int value in assign` and `cannot convert o (variable of type []int) to type string` – noraj Apr 03 '23 at 14:01
I wrote the following Reverse
function which respects UTF8 encoding and combined characters:
// Reverse reverses the input while respecting UTF8 encoding and combined characters
func Reverse(text string) string {
textRunes := []rune(text)
textRunesLength := len(textRunes)
if textRunesLength <= 1 {
return text
}
i, j := 0, 0
for i < textRunesLength && j < textRunesLength {
j = i + 1
for j < textRunesLength && isMark(textRunes[j]) {
j++
}
if isMark(textRunes[j-1]) {
// Reverses Combined Characters
reverse(textRunes[i:j], j-i)
}
i = j
}
// Reverses the entire array
reverse(textRunes, textRunesLength)
return string(textRunes)
}
func reverse(runes []rune, length int) {
for i, j := 0, length-1; i < length/2; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
}
// isMark determines whether the rune is a marker
func isMark(r rune) bool {
return unicode.Is(unicode.Mn, r) || unicode.Is(unicode.Me, r) || unicode.Is(unicode.Mc, r)
}
I did my best to make it as efficient and readable as possible. The idea is simple, traverse through the runes looking for combined characters then reverse the combined characters' runes in-place. Once we have covered them all, reverse the runes of the entire string also in-place.
Say we would like to reverse this string bròwn
. The ò
is represented by two runes, one for the o
and one for this unicode \u0301a
that represents the "grave".
For simplicity, let's represent the string like this bro'wn
. The first thing we do is look for combined characters and reverse them. So now we have the string br'own
. Finally, we reverse the entire string and end up with nwo'rb
. This is returned to us as nwòrb
You can find it here https://github.com/shomali11/util if you would like to use it.
Here are some test cases to show a couple of different scenarios:
func TestReverse(t *testing.T) {
assert.Equal(t, Reverse(""), "")
assert.Equal(t, Reverse("X"), "X")
assert.Equal(t, Reverse("b\u0301"), "b\u0301")
assert.Equal(t, Reverse("⚽"), "⚽")
assert.Equal(t, Reverse("Les Mise\u0301rables"), "selbare\u0301siM seL")
assert.Equal(t, Reverse("ab\u0301cde"), "edcb\u0301a")
assert.Equal(t, Reverse("This `\xc5` is an invalid UTF8 character"), "retcarahc 8FTU dilavni na si `�` sihT")
assert.Equal(t, Reverse("The quick bròwn 狐 jumped over the lazy 犬"), "犬 yzal eht revo depmuj 狐 nwòrb kciuq ehT")
}

- 1,385
- 15
- 7
-
3So far this is the only answer that works with a string that includes grapheme clustered chars (combined chars) such as `2️⃣` which reverses to `2️⃣`. Most of the other answers return `⃣️2`. https://paiza.io/projects/K8_kOmxn-cGRR3ksh1vFtw – KEINOS Oct 16 '20 at 04:37
-
While certainly better than the other implementations, it only works with a small subset of grapheme clusters possible according to the Unicode specification. For example, ️ reverses to ️ and reverses to . If you care about correct Unicode handling, you should use: https://pkg.go.dev/github.com/rivo/uniseg#ReverseString – Oliver Nov 15 '22 at 18:24
I noticed this question when Simon posted his solution which, since strings are immutable, is very inefficient. The other proposed solutions are also flawed; they don't work or they are inefficient.
Here's an efficient solution that works, except when the string is not valid UTF-8 or the string contains combining characters.
package main
import "fmt"
func Reverse(s string) string {
n := len(s)
runes := make([]rune, n)
for _, rune := range s {
n--
runes[n] = rune
}
return string(runes[n:])
}
func main() {
fmt.Println(Reverse(Reverse("Hello, 世界")))
fmt.Println(Reverse(Reverse("The quick brown 狐 jumped over the lazy 犬")))
}
-
1
-
3
-
could you please explain a bit more on why that is? I made a short program and it works there, but maybe those cases you talk about aren't triggered there? http://play.golang.org/p/yk1sAwFjol – Aug 20 '13 at 09:52
-
1@Tommy: Your short program merely demonstrates that the NUL character is a NOP when sent to a printer or terminal. Your Reverse2 function fails for non-ASCII UTF-8 encoded strings. I've revised your short program so that it's a valid test: http://play.golang.org/p/Ic5G5QEO93 – peterSO Aug 21 '13 at 02:19
-
1One more wrong "solution" that doesn't handle combining characters properly. – dolmen Jul 26 '16 at 12:42
//Reverse reverses string using strings.Builder. It's about 3 times faster
//than the one with using a string concatenation
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()
}
//Reverse reverses string using string
func Reverse(in string) (out string) {
for _, r := range in {
out = string(r) + out
}
return
}
BenchmarkReverseStringConcatenation-8 1000000 1571 ns/op 176 B/op 29 allocs/op
BenchmarkReverseStringsBuilder-8 3000000 499 ns/op 56 B/op 6 allocs/op
Using strings.Builder is about 3 times faster than using string concatenation

- 83,883
- 25
- 248
- 179
-
1I wonder, why this question has no upvotes despite being most accurate answer – Nilesh Jun 24 '20 at 13:28
-
1
-
Doesn't work: bròwn becomes nẁorb. See: https://go.dev/play/p/MRyIb0fYQ6y – prnsml Aug 16 '23 at 16:03
A simple stroke with rune
:
func ReverseString(s string) string {
runes := []rune(s)
size := len(runes)
for i, j := 0, size-1; i < size>>1; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func main() {
fmt.Println(ReverseString("Abcdefg 汉语 The God"))
}
: doG ehT 语汉 gfedcbA

- 295
- 3
- 6
-
-
> using i,j 2 indices might be better, and size/2 can be size >> 1 Updated – Eric May 05 '23 at 03:21
-
Here is quite different, I would say more functional approach, not listed among other answers:
func reverse(s string) (ret string) {
for _, v := range s {
defer func(r rune) { ret += string(r) }(v)
}
return
}

- 685
- 7
- 10
-
I'm pretty sure it is not the fastest solution, but it shows how return variable `ret` is kept in closure for further processing, by each defer function. – Vladimir Bauer Jun 29 '16 at 14:29
-
2
-
1
-
Performance of this one may be improved in Go 1.14. At least [release notes](https://tip.golang.org/doc/go1.14#runtime) claims to have zero overhead of defer. – Vladimir Bauer Jan 02 '20 at 12:17
func ReverseString(str string) string {
output :=""
for _, char := range str {
output = string(char) + output
}
return output
}
// "Luizpa" -> "apziuL"
// "123日本語" -> "語本日321"
// "⚽" -> "⚽"
// "´a´b´c´" -> "´c´b´a´"

- 133
- 3
- 7
-
That won't work with unicode combining characters, as I explain in https://stackoverflow.com/a/62743214/6309. See my method vs. yours in https://play.golang.org/p/dmvUdPMY4M1 – VonC Apr 20 '21 at 07:18
This is the fastest implementation
func Reverse(s string) string {
size := len(s)
buf := make([]byte, size)
for start := 0; start < size; {
r, n := utf8.DecodeRuneInString(s[start:])
start += n
utf8.EncodeRune(buf[size-start:], r)
}
return string(buf)
}
const (
s = "The quick brown 狐 jumped over the lazy 犬"
reverse = "犬 yzal eht revo depmuj 狐 nworb kciuq ehT"
)
func TestReverse(t *testing.T) {
if Reverse(s) != reverse {
t.Error(s)
}
}
func BenchmarkReverse(b *testing.B) {
for i := 0; i < b.N; i++ {
Reverse(s)
}
}

- 12,062
- 4
- 64
- 92
-
Did you benchmark the solutions before claiming it's the fastest implementation ? – Denys Séguret Sep 05 '14 at 07:25
-
yes i did, that is why the BenchmarkReverse code is present :) . However i do not have the results anymore. – rmuller Sep 23 '14 at 17:30
-
3Fast solution, but still wrong as it doesn't handle combining characters properly. – dolmen Jul 26 '16 at 12:58
-
Is it true as @dolmen says that this does not handle combining characters? Is there a solution here that does? – geraldss Oct 13 '16 at 18:14
You could also import an existing implementation:
import "4d63.com/strrev"
Then:
strrev.Reverse("abåd") // returns "dåba"
Or to reverse a string including unicode combining characters:
strrev.ReverseCombining("abc\u0301\u031dd") // returns "d\u0301\u031dcba"
These implementations supports correct ordering of unicode multibyte and combing characters when reversed.
Note: Built-in string reverse functions in many programming languages do not preserve combining, and identifying combining characters requires significantly more execution time.

- 1,886
- 24
- 23
If you need to handle grapheme clusters, use unicode or regexp module.
package main
import (
"unicode"
"regexp"
)
func main() {
str := "\u0308" + "a\u0308" + "o\u0308" + "u\u0308"
println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme(str))
println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme2(str))
}
func ReverseGrapheme(str string) string {
buf := []rune("")
checked := false
index := 0
ret := ""
for _, c := range str {
if !unicode.Is(unicode.M, c) {
if len(buf) > 0 {
ret = string(buf) + ret
}
buf = buf[:0]
buf = append(buf, c)
if checked == false {
checked = true
}
} else if checked == false {
ret = string(append([]rune(""), c)) + ret
} else {
buf = append(buf, c)
}
index += 1
}
return string(buf) + ret
}
func ReverseGrapheme2(str string) string {
re := regexp.MustCompile("\\PM\\pM*|.")
slice := re.FindAllString(str, -1)
length := len(slice)
ret := ""
for i := 0; i < length; i += 1 {
ret += slice[length-1-i]
}
return ret
}

- 4,540
- 1
- 39
- 42
-
I'd like to give you 1'000 upvotes. All other implementations on this page reverse a STRING incorrectly (a STRING is NOT a sequence of chars). – Stefan Steiger Mar 30 '16 at 14:26
-
This doesn't work. If you double reverse the string you do not get the original string. The leading Combining Diaeresis (\u0308), used in this example combines with preceding characters creating a double umlaut 'a' when reversed. If `str` is output quoted it modifies the leading quote! – Joshua Kolden Jan 26 '18 at 05:26
This code preserves sequences of combining characters intact, and should work with invalid UTF-8 input too.
package stringutil
import "code.google.com/p/go.text/unicode/norm"
func Reverse(s string) string {
bound := make([]int, 0, len(s) + 1)
var iter norm.Iter
iter.InitString(norm.NFD, s)
bound = append(bound, 0)
for !iter.Done() {
iter.Next()
bound = append(bound, iter.Pos())
}
bound = append(bound, len(s))
out := make([]byte, 0, len(s))
for i := len(bound) - 2; i >= 0; i-- {
out = append(out, s[bound[i]:bound[i+1]]...)
}
return string(out)
}
It could be a little more efficient if the unicode/norm primitives allowed iterating through the boundaries of a string without allocating. See also https://code.google.com/p/go/issues/detail?id=9055 .

- 6,252
- 4
- 31
- 25
-
There is no such "invalid UTF-8 input" in string values: when converting from `[]byte` to `string` Go replaces "invalid UTF-8 input" by a valid codepoint `\uFFFD`. – dolmen Apr 25 '17 at 15:36
-
I don't understand the above comment. Are you saying that the behaviour of this code is wrong when presented with a string containing invalid UTF-8 ? – rog Apr 26 '17 at 16:25
-
No. I'm saying that invalid UTF-8 in a Go `string` doesn't exist. But it can exist in a `[]byte`. – dolmen May 02 '17 at 14:04
-
A Go string can contain exactly as much invalid utf-8 as a []byte. For example: https://play.golang.org/p/PG0I4FJfEN – rog May 03 '17 at 15:02
It's assuredly not the most memory efficient solution, but for a "simple" UTF-8 safe solution the following will get the job done and not break runes.
It's in my opinion the most readable and understandable on the page.
func reverseStr(str string) (out string) {
for _, s := range str {
out = string(s) + out
}
return
}

- 3,105
- 3
- 32
- 51
The following two methods run faster than the fastest solution that preserve combining characters, though that's not to say I'm missing something in my benchmark setup.
//input string s
bs := []byte(s)
var rs string
for len(bs) > 0 {
r, size := utf8.DecodeLastRune(bs)
rs += fmt.Sprintf("%c", r)
bs = bs[:len(bs)-size]
} // rs has reversed string
Second method inspired by this
//input string s
bs := []byte(s)
cs := make([]byte, len(bs))
b1 := 0
for len(bs) > 0 {
r, size := utf8.DecodeLastRune(bs)
d := make([]byte, size)
_ = utf8.EncodeRune(d, r)
b1 += copy(cs[b1:], d)
bs = bs[:len(bs) - size]
} // cs has reversed bytes
-
2Here is what you are missing in your benchmark: your solution is faster because it doesn't preserve combining characters. It is just unfair to compare them. – dolmen Apr 25 '17 at 15:48
-
Apart from not handling combined characters, this answer is so far the fastest in this thread. It is the only one that avoids doing 2 allocations: one per rune slice, one to make a string back out of it – Maksim Gayduk Apr 03 '22 at 19:26
NOTE: This answer is from 2009, so there are probably better solutions out there by now.
Looks a bit 'roundabout', and probably not very efficient, but illustrates how the Reader interface can be used to read from strings. IntVectors also seem very suitable as buffers when working with utf8 strings.
It would be even shorter when leaving out the 'size' part, and insertion into the vector by Insert, but I guess that would be less efficient, as the whole vector then needs to be pushed back by one each time a new rune is added.
This solution definitely works with utf8 characters.
package main
import "container/vector";
import "fmt";
import "utf8";
import "bytes";
import "bufio";
func
main() {
toReverse := "Smørrebrød";
fmt.Println(toReverse);
fmt.Println(reverse(toReverse));
}
func
reverse(str string) string {
size := utf8.RuneCountInString(str);
output := vector.NewIntVector(size);
input := bufio.NewReader(bytes.NewBufferString(str));
for i := 1; i <= size; i++ {
rune, _, _ := input.ReadRune();
output.Set(size - i, rune);
}
return string(output.Data());
}

- 2,240
- 2
- 15
- 23
-
1
-
2
-
2
-
3@OliverMason It's never too late to fix (or delete) an imperfect solution. – dolmen Jun 22 '18 at 20:36
For simple strings it possible to use such construction:
func Reverse(str string) string {
if str != "" {
return Reverse(str[1:]) + str[:1]
}
return ""
}
For Unicode strings it might look like this:
func RecursiveReverse(str string) string {
if str == "" {
return ""
}
runes := []rune(str)
return RecursiveReverse(string(runes[1:])) + string(runes[0])
}

- 295
- 3
- 6

- 27
- 3
-
Wouldn't this create extra memory ? Its not in-place isn't it ? – Mirav T. Mehta May 21 '22 at 13:55
func Reverse(s string) string {
r := []rune(s)
var output strings.Builder
for i := len(r) - 1; i >= 0; i-- {
output.WriteString(string(r[i]))
}
return output.String()
}

- 41
- 4
-
2Thanks for the answer, but with 32 other answers and some that are [virtually identical](https://stackoverflow.com/a/57645384/6243352), does this really add anything new to the discourse? If so, please justify it with some explanation of why it's useful. Code-only answers are considered low-quality. – ggorlen Oct 11 '20 at 02:10
Simple, Sweet and Performant
func reverseStr(str string) string {
strSlice := []rune(str) //converting to slice of runes
length := len(strSlice)
for i := 0; i < (length / 2); i++ {
strSlice[i], strSlice[length-i-1] = strSlice[length-i-1], strSlice[i]
}
return string(strSlice) //converting back to string
}

- 2,687
- 24
- 24
Reversing a string by word is a similar process. First, we convert the string into an array of strings where each entry is a word. Next, we apply the normal reverse loop to that array. Finally, we smush the results back together into a string that we can return to the caller.
package main
import (
"fmt"
"strings"
)
func reverse_words(s string) string {
words := strings.Fields(s)
for i, j := 0, len(words)-1; i < j; i, j = i+1, j-1 {
words[i], words[j] = words[j], words[i]
}
return strings.Join(words, " ")
}
func main() {
fmt.Println(reverse_words("one two three"))
}

- 241
- 4
- 8
Another hack is to use built-in language features, for example, defer
:
package main
import "fmt"
func main() {
var name string
fmt.Scanln(&name)
for _, char := range []rune(name) {
defer fmt.Printf("%c", char) // <-- LIFO does it all for you
}
}

- 764
- 2
- 9
- 27
Recognising unicode code points is one thing, but how about grapheme clusters?
For example, ☠️ is composed from 4 unicode code points / runes, and reversing such a string on the basis of runes will produce garbage. Not good.
Read more about Unicode segmentation in rivo/uniseg docs.
Here's the reversal of a string, using this package:
func reverseSlice[T any](s []T) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
func reverse(s string) string {
var grStrings []string
gr := uniseg.NewGraphemes(s)
for gr.Next() {
grStrings = append(grStrings, gr.Str())
}
reverseSlice(grStrings)
return strings.Join(grStrings, "")
}

- 8,575
- 4
- 56
- 95
rune is a type, so use it. Moreover, Go doesn't use semicolons.
func reverse(s string) string {
l := len(s)
m := make([]rune, l)
for _, c := range s {
l--
m[l] = c
}
return string(m)
}
func main() {
str := "the quick brown 狐 jumped over the lazy 犬"
fmt.Printf("reverse(%s): [%s]\n", str, reverse(str))
}

- 803
- 6
- 7
-
-
1One more wrong "solution" that doesn't handle combining characters properly. – dolmen Jul 26 '16 at 12:57
A version which I think works on unicode. It is built on the utf8.Rune functions:
func Reverse(s string) string {
b := make([]byte, len(s));
for i, j := len(s)-1, 0; i >= 0; i-- {
if utf8.RuneStart(s[i]) {
rune, size := utf8.DecodeRuneInString(s[i:len(s)]);
utf8.EncodeRune(rune, b[j:j+size]);
j += size;
}
}
return string(b);
}

- 14,880
- 4
- 24
- 19
try below code:
package main
import "fmt"
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 main() {
fmt.Printf("%v\n", reverse("abcdefg"))
}
for more info check http://golangcookbook.com/chapters/strings/reverse/
and http://www.dotnetperls.com/reverse-string-go

- 2,544
- 3
- 22
- 41
func reverseString(someString string) string {
runeString := []rune(someString)
var reverseString string
for i := len(runeString)-1; i >= 0; i -- {
reverseString += string(runeString[i])
}
return reverseString
}

- 39
- 4
Strings are immutable object in golang, unlike C inplace reverse is not possible with golang. With C , you can do something like,
void reverseString(char *str) {
int length = strlen(str)
for(int i = 0, j = length-1; i < length/2; i++, j--)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
But with golang, following one, uses byte to convert the input into bytes first and then reverses the byte array once it is reversed, convert back to string before returning. works only with non unicode type string.
package main
import "fmt"
func main() {
s := "test123 4"
fmt.Println(reverseString(s))
}
func reverseString(s string) string {
a := []byte(s)
for i, j := 0, len(s)-1; i < j; i++ {
a[i], a[j] = a[j], a[i]
j--
}
return string(a)
}

- 694
- 1
- 8
- 24
package main
import "fmt"
func main() {
var str string
fmt.Println("Enter a string: ")
fmt.Scanln(&str)
var reversed string = ""
for i := len(str) - 1; i >= 0; i-- {
reversed += string(str[i])
}
fmt.Println(reversed)
}

- 190
- 1
- 4
Here is yet another solution:
func ReverseStr(s string) string {
chars := []rune(s)
rev := make([]rune, 0, len(chars))
for i := len(chars) - 1; i >= 0; i-- {
rev = append(rev, chars[i])
}
return string(rev)
}
However, yazu's solution above is more elegant since he reverses the []rune
slice in place.

- 19,598
- 6
- 52
- 45
Yet Another Solution (tm) :
package main
import "fmt"
type Runes []rune
func (s Runes) Reverse() (cp Runes) {
l := len(s); cp = make(Runes, l)
// i <= 1/2 otherwise it will mess up with odd length strings
for i := 0; i <= l/2; i++ {
cp[i], cp[l-1-i] = s[l-1-i], s[i]
}
return cp
}
func (s Runes) String() string {
return string(s)
}
func main() {
input := "The quick brown 狐 jumped over the lazy 犬 +odd"
r := Runes(input)
output := r.Reverse()
valid := string(output.Reverse()) == input
fmt.Println(len(r), len(output), r, output.Reverse(), valid)
}

- 95,033
- 20
- 184
- 185
package reverseString
import "strings"
// ReverseString - output the reverse string of a given string s
func ReverseString(s string) string {
strLen := len(s)
// The reverse of a empty string is a empty string
if strLen == 0 {
return s
}
// Same above
if strLen == 1 {
return s
}
// Convert s into unicode points
r := []rune(s)
// Last index
rLen := len(r) - 1
// String new home
rev := []string{}
for i := rLen; i >= 0; i-- {
rev = append(rev, string(r[i]))
}
return strings.Join(rev, "")
}
Test
package reverseString
import (
"fmt"
"strings"
"testing"
)
func TestReverseString(t *testing.T) {
s := "GO je úžasné!"
r := ReverseString(s)
fmt.Printf("Input: %s\nOutput: %s", s, r)
revR := ReverseString(r)
if strings.Compare(s, revR) != 0 {
t.Errorf("Expecting: %s\n. Got: %s\n", s, revR)
}
}
Output
Input: GO je úžasné!
Output: !énsažú ej OG
PASS
ok github.com/alesr/reverse-string 0.098s

- 1,102
- 1
- 19
- 26
-
1This works if the input is in NFC. But as most other wrong solutions here it doesn't work with combining characters. – dolmen Apr 25 '17 at 15:48
func reverseStr(b string) {
for _, v := range []rune(b) {
defer fmt.Printf("%c", v)
}
}
Defer is useful for this as it is LIFO - Last in First Out

- 369
- 1
- 4
- 9