Como reverter uma string em Go?


103

Como podemos reverter uma string simples em Go?


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

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

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 
}

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

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


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

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=.


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

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

+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


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
}

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

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 .


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
}

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.


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
}

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

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

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

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

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

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


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

-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

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
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.