Como reverter uma string em Go?

103

Como podemos reverter uma string simples em Go?

user211499
fonte
1
Pelo que entendi, as soluções fornecidas a seguir não funcionam com caracteres pré-compostos ou combinados, como dar em a+´vez de á. Eu me pergunto como isso poderia ser levado em consideração, sem normalizá-lo.
siritinga
Se você está confuso com um grande número de respostas semelhantes, verifique meu benchmark .
Salvador Dali

Respostas:

94

Em Go1, a runa é um tipo embutido.

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)
}
yazu
fonte
4
você não pode usar len () em Go para descobrir o comprimento de uma string / Array / Slice etc ... Por quê? - len () em Go significa o tamanho da entrada em bytes. Não corresponde ao seu comprimento. - Nem todas as runas do utf8 são do mesmo tamanho. Pode ser 1, 2, 4 ou 8. - Você deve usar o método RuneCountInString do pacote unicode / ut8 para obter o comprimento da runa.
Anvesh Checka
15
@AnveshChecka, isso está incorreto. Veja golang.org/pkg/builtin/#len - len () em uma fatia definitivamente retorna o número de elementos, não o tamanho em bytes. Uma fatia de runas é a maneira correta de fazer isso.
chowey de
3
@ рытфолд Isso não funciona com a combinação de caracteres. Consulte play.golang.org/p/sBgZAV7gCb , o caractere de combinação não é trocado por sua base.
chowey de
53

Russ Cox, na lista de discussão golang-nuts , sugere

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)
}
user181548
fonte
20
Eu gosto de como eles o forçam a pensar sobre codificações.
György Andrasek
10
fora do tópico: por que é [nozes golang] e não [nozes]?
Jimmy,
2
Uau, qual é a dupla atribuição ao reverter? Interessante. Agora, pense em uma corda com um número ímpar de runas. O do meio recebe tratamento especial, com o resultado final correto, no entanto. :) Uma pequena otimização interessante que eu não teria pensado de imediato.
Kissaki
4
Não entendo por que essa conversão para runa, por que não rune:=[]rune(input)?
siritinga
1
Você não precisa do primeiro para o loop de alcance. saída: = [] runa (entrada); n: = len (saída) E você não precisa da runa = runa [0: n]
dvallejo
29

Isso funciona, sem toda a confusão com as funções:

func Reverse(s string) (result string) {
  for _,v := range s {
    result = string(v) + result
  }
  return 
}
Simon
fonte
6
Embora funcione, como as strings são imutáveis, é muito ineficiente. Publiquei uma solução mais eficiente.
peterSO
5
Isso é muito fácil de entender. Torne mais difícil :-) (e, "mais um" por simplesmente continuar com isso)
Roboprog
2
Esta é a melhor resposta, a menos que inverter as strings seja o seu gargalo.
Banjocat
1
@dolmen - por que isso não lidaria com a combinação de caracteres? um intervalo em uma string retorna uma runa que é um codepoint.
Stan R.
1
@StanR. Uma runa não é um glifo. Um glifo pode ser feito de vários pontos de código / runas. Consulte reedbeta.com/blog/programmers-intro-to-unicode/#combining-marks Os pontos de código reversos anexarão marcas de combinação a um ponto de código base diferente.
Dolmen de
14

Isso funciona em strings Unicode considerando 2 coisas:

  • alcance funciona em string enumerando caracteres Unicode
  • string pode ser construída a partir de fatias inteiras, onde cada elemento é um caractere Unicode.

Então aqui vai:

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);
}
Randy Sugianto 'Yuku'
fonte
Eu atribuiria i:=len(o)-1e dobraria o for em uma única linha for _, c:=range s { o[i--]=c; }. Cara, eu ODEIO o sem parênteses - isso é permitido:for(_, c:=range s) { o[i--]=c; }
Lawrence Dol
Você poderia explicar o que _ faz?
Lawrence Dol de
6
@Software_Monkey: o [i--] = c não é permitido no Go. - e ++ são declarações, não expressões. _ significa descartar (ignorar) essa variável.
Randy Sugianto 'Yuku'
1
com go 1.1+ ele retorna um erro na linha string ([] int), se em vez disso [] tipo de runa for usado para o, tudo funciona
Otuk
1
@yuku: Ainda falha em s: = "Les Mise \ u0301rables"
Stefan Steiger
13

De projetos de exemplo Go: golang / example / stringutil / reverse.go , de 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)
}

Vá ao Playground para inverter uma corda

Depois de inverter a string "bròwn", o resultado correto deve ser "nwòrb", não "nẁorb".
Observe a sepultura acima da letra o.


Para preservar caracteres de combinação Unicode como "as⃝df̅" com o resultado reverso "f̅ds⃝a",
consulte outro código listado abaixo:

http://rosettacode.org/wiki/Reverse_a_string#Go

Ivan Chau
fonte
2
Obrigado por esclarecer a diferença de stackoverflow.com/a/10030772/3093387 - parece que essas duas soluções diferem na forma como lidam com strings como "bròwn".
josliber
Obrigado por mencionar a solução Rosettacode que lida com a combinação de caracteres
dolmen
11

Percebi essa pergunta quando Simon postou sua solução que, como as strings são imutáveis, é muito ineficiente. As outras soluções propostas também são falhas; eles não funcionam ou são ineficientes.

Esta é uma solução eficiente que funciona, exceto quando a string não é UTF-8 válida ou a string contém caracteres combinados.

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 犬")))
}
PeterSO
fonte
1
return string (runas) Funciona também.
3
@Tommy: Não, return string(runes)não funciona para todos os casos.
peterSO
você poderia explicar um pouco mais sobre o porquê disso? Fiz um programa curto e funciona lá, mas talvez os casos de que você fala não sejam acionados aí? play.golang.org/p/yk1sAwFjol
1
@Tommy: Seu programa curto meramente demonstra que o caractere NUL é um NOP quando enviado a uma impressora ou terminal. A função Reverse2 falha para strings codificadas não ASCII UTF-8. Revisei
peterSO
Mais uma "solução" errada que não lida com a combinação de caracteres corretamente.
Dolmen
9

Existem muitas respostas aqui. Alguns deles são duplicatas claras. Mas, mesmo da esquerda, é difícil selecionar a melhor solução.

Então eu fui pelas respostas, joguei fora a que não funciona para Unicode e também removi as duplicatas. Eu comparei os sobreviventes para encontrar o mais rápido. Então, aqui estão os resultados com atribuição (se você notar as respostas que perdi, mas vale a pena adicionar, sinta-se à vontade para modificar o 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

Então, aqui está o método mais rápido de 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)
}

Por alguma razão, não consigo adicionar um benchmark, então você pode copiá-lo PlayGround(você não pode executar testes lá). Renomeie-o e executego test -bench=.

Salvador Dalí
fonte
Nenhuma dessas "soluções" lida com a combinação de marcas corretamente.
Dolmen de
6

Escrevi a seguinte Reversefunção que respeita a codificação UTF8 e os caracteres combinados:

// 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)
}

Fiz o meu melhor para torná-lo o mais eficiente e legível possível. A ideia é simples, atravesse as runas procurando por caracteres combinados e então inverta as runas dos personagens combinados no local. Depois de cobrir todos eles, inverta as runas de toda a corda no lugar.

Digamos que gostaríamos de reverter essa string bròwn. O òé representado por duas runas, uma para o oe outra para este unicode \u0301aque representa o "túmulo".

Para simplificar, vamos representar a string desta forma bro'wn. A primeira coisa que fazemos é procurar caracteres combinados e invertê-los. Portanto, agora temos a corda br'own. Finalmente, invertemos toda a string e terminamos com nwo'rb. Isso é devolvido a nós comonwòrb

Você pode encontrá-lo aqui https://github.com/shomali11/util se desejar usá-lo.

Aqui estão alguns casos de teste para mostrar alguns cenários diferentes:

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")
}
Raed Shomali
fonte
3

Com base na sugestão original de Stephan202 e parece funcionar para strings Unicode:

import "strings";

func Reverse( orig string ) string {
    var c []string = strings.Split( orig, "", 0 );

    for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 {
        c[i], c[j] = c[j], c[i]
    }

    return strings.Join( c, "" );
}

Alternativo, não usando o pacote de strings, mas não 'seguro para Unicode':

func Reverse( s string ) string {
    b := make([]byte, len(s));
    var j int = len(s) - 1;
    for i := 0; i <= j; i++ {
        b[j-i] = s[i]
    }

    return string ( b );
}
martin clayton
fonte
+1. Isso funciona. Mas devo dizer que é um tanto estranho (por enquanto) que a divisão e a junção sejam necessárias para uma tarefa tão simples ...
Stephan202
@martin: desculpe pela edição. Eu colei acidentalmente minha resposta atualizada em sua pergunta ... estou com muita vergonha .
Stephan202
@Stephan - sem problema. Eu adicionei uma solução alternativa, com base na função Bytes do pacote de strings.
Martin Clayton
@Nosradena: Voltei no mesmo minuto (fiquei surpreso ao ver que Martin atualizou sua resposta com exatamente o mesmo texto que eu tinha acabado de escrever ... e então me ocorreu;)
Stephan202
@martin: a segunda versão fica melhor se você me perguntar :)
Stephan202
3
//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

Usar strings.Builder é cerca de 3 vezes mais rápido do que usar concatenação de string

Vlad Bezden
fonte
1
Eu me pergunto por que essa pergunta não tem votos positivos apesar de ser a resposta mais precisa
Nilesh
3

Aqui é bem diferente, eu diria uma abordagem mais funcional, não listada entre outras respostas:

func reverse(s string) (ret string) {
    for _, v := range s {
        defer func(r rune) { ret += string(r) }(v)
    }
    return
}
Vladimir Bauer
fonte
Tenho certeza de que não é a solução mais rápida, mas mostra como a variável de retorno reté mantida em fechamento para processamento posterior, por cada função defer.
Vladimir Bauer
Lento e não lida com a combinação de caracteres corretamente.
Dolmen
1
Não tenho certeza de quão rápido isso é, mas é lindo.
donatJ
O desempenho deste pode ser melhorado no Go 1.14. Pelo menos as notas de versão afirmam ter zero overhead de adiamento.
Vladimir Bauer
2

Esta é a implementação mais rápida

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)
    }
}
rmuller
fonte
Você comparou as soluções antes de afirmar que é a implementação mais rápida?
Denys Séguret
sim, é por isso que o código BenchmarkReverse está presente :). No entanto, não tenho mais os resultados.
rmuller
Solução rápida, mas ainda errada, pois não lida com a combinação de caracteres corretamente.
Dolmen
É verdade que @dolmen diz que isso não lida com a combinação de caracteres? Existe uma solução aqui que sim?
geraldss
2

Este código preserva as sequências de caracteres combinados intactas e também deve funcionar com entrada UTF-8 inválida.

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)
}

Poderia ser um pouco mais eficiente se as primitivas unicode / norm permitissem a iteração pelos limites de uma string sem alocação. Consulte também https://code.google.com/p/go/issues/detail?id=9055 .

rog
fonte
Não existe tal "entrada UTF-8 inválida" em valores de string: ao converter de []bytepara stringGo substitui "entrada UTF-8 inválida" por um ponto de código válido \uFFFD.
Dolmen de
Eu não entendo o comentário acima. Você está dizendo que o comportamento desse código está errado quando apresentado com uma string contendo UTF-8 inválido?
rog
Não. Estou dizendo que o UTF-8 inválido em um Go stringnão existe. Mas pode existir em um []byte.
dolmen
Uma string Go pode conter exatamente tanto utf-8 inválido quanto um byte []. Por exemplo: play.golang.org/p/PG0I4FJfEN
rog
2

Se você precisar lidar com clusters de grafemas, use o módulo Unicode ou regexp.

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
}
masakielástico
fonte
Eu gostaria de dar a você 1.000 votos positivos. Todas as outras implementações nesta página invertem um STRING incorretamente (um STRING NÃO é uma sequência de caracteres).
Stefan Steiger
Isso não funciona. Se você inverter a string, não obterá a string original. O Diaeresis Combinante principal (\ u0308), usado neste exemplo, combina-se com os caracteres precedentes, criando um trema duplo 'a' quando invertido. Se a strsaída for citada, ela modifica a citação inicial!
Joshua Kolden
2

Você também pode importar uma implementação existente:

import "4d63.com/strrev"

Então:

strrev.Reverse("abåd") // returns "dåba"

Ou para inverter uma string incluindo caracteres de combinação Unicode:

strrev.ReverseCombining("abc\u0301\u031dd") // returns "d\u0301\u031dcba"

Essas implementações suportam a ordenação correta de caracteres multibyte Unicode e combing quando invertidos.

Nota: As funções reversas de string integradas em muitas linguagens de programação não preservam a combinação, e a identificação de caracteres combinados requer muito mais tempo de execução.

Leigh McCulloch
fonte
1

Certamente não é a solução mais eficiente em termos de memória, mas para uma solução segura UTF-8 "simples", o seguinte fará o trabalho e não quebrará runas.

Na minha opinião, é o mais legível e compreensível da página.

func reverseStr(str string) (out string) {
    for _, s := range str {
        out = string(s) + out
    }

    return
}
donatJ
fonte
1

Os dois métodos a seguir são executados mais rapidamente do que a solução mais rápida que preserva a combinação de caracteres , embora isso não queira dizer que esteja faltando algo em minha configuração de benchmark.

//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

Segundo método inspirado neste

//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
Sridhar
fonte
Aqui está o que está faltando em seu benchmark: sua solução é mais rápida porque não preserva a combinação de caracteres. É simplesmente injusto compará-los.
Dolmen de
1

NOTA: Esta resposta é de 2009, então provavelmente existem soluções melhores por aí agora.


Parece um pouco "indireto" e provavelmente não é muito eficiente, mas ilustra como a interface do Reader pode ser usada para ler strings. IntVectors também parecem muito adequados como buffers ao trabalhar com strings utf8.

Seria ainda mais curto deixando de fora a parte do 'tamanho' e a inserção no vetor por Insert, mas acho que seria menos eficiente, pois o vetor inteiro precisa ser empurrado para trás em um cada vez que uma nova runa é adicionada .

Esta solução definitivamente funciona com caracteres utf8.

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());
}
Oliver Mason
fonte
Por que você adiciona todos os pontos-e-vírgulas finais?
Morteza R
@olivier-mason É hora de aprender sobre gofmt ao compartilhar código Go.
Dolmen de
1
Essa resposta foi de oito anos atrás.
Oliver Mason
@OliverMason Nunca é tarde para consertar (ou excluir) uma solução imperfeita.
Dolmen de
0

Uma versão que acho que funciona em Unicode. Ele é baseado nas funções utf8.Rune:

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);
}
Jonathan Wright
fonte
0

runa é um tipo, então use-a. Além disso, Go não usa ponto-e-vírgula.

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))
}
Walter
fonte
Ele usou ponto e vírgula quando a pergunta foi postada.
OneOfOne
Mais uma "solução" errada que não lida com a combinação de caracteres corretamente.
Dolmen
0

Para strings simples, é possível usar essa construção:

func Reverse(str string) string {
    if str != "" {
        return Reverse(str[1:]) + str[:1]
    }
    return ""   
}
Sergo Kurbanov
fonte
-1

Aqui está outra solução:

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)
}

No entanto, a solução de yazu acima é mais elegante, pois ele inverte a []runefatia no lugar.

Jabba
fonte
-1

Ainda outra solução (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)
}
OneOfOne
fonte
-1
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, "")
}

Teste

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)
    }
}

Resultado

Input: GO je úžasné!
Output: nsažú ej OG
PASS
ok      github.com/alesr/reverse-string 0.098s
Alessandro Resta
fonte
Isso funciona se a entrada for em NFC. Mas como a maioria das outras soluções erradas aqui, ela não funciona com a combinação de caracteres.
Dolmen de
-1
    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
    }
saurabh
fonte