102

If I have the string "12121211122" and I want to get the last 3 characters (e.g. "122"), is that possible in Go? I've looked in the string package and didn't see anything like getLastXcharacters.

030
  • 10,842
  • 12
  • 78
  • 123
sourcey
  • 2,481
  • 5
  • 16
  • 13

2 Answers2

176

You can use a slice expression on a string to get the last three bytes.

s      := "12121211122"
first3 := s[0:3]
last3  := s[len(s)-3:]

Or if you're using unicode you can do something like:

s      := []rune("世界世界世界")
first3 := string(s[0:3])
last3  := string(s[len(s)-3:])

Check Strings, bytes, runes and characters in Go and Slice Tricks.

OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • @tommywild from http://blog.golang.org/slices: Strings are actually very simple: they are just ***read-only slices of bytes*** with a bit of extra syntactic support from the language. – OneOfOne Oct 02 '14 at 19:03
  • @tommywild also keep in mind that `sh := (*reflect.SliceHeader)(unsafe.Pointer(&str)); sh.Cap = sh.Len; bytes := *(*[]byte)(unsafe.Pointer(sh))` is perfectly valid, of course modifying it will result in a memory corruption. – OneOfOne Oct 02 '14 at 19:07
  • 4
    Consider that the question asks about characters, not bytes, and in a string, not in a slice of runes. In that context the answer does not seem match the question. The "string" portion of the answer [fails on unicode input](https://play.golang.org/p/c4B4XjZW5p), while the slice of runes is not applicable unless a method provided to convert string into slice of runes to answer the question. I would love to know an efficient answer better than that of @SimonFox . Even using `utf8.RuneCountInString(s)` is counterproductive as it scans the string anyway. – Vlad Didenko Mar 24 '16 at 03:18
  • truly a non-pythonic way, using s[-1] would have been so simple. – Rahul Bali Dec 31 '22 at 18:00
18

The answer depends on what you mean by "characters". If you mean bytes then:

s := "12121211122"
lastByByte := s[len(s)-3:]

If you mean runes in a utf-8 encoded string, then:

s := "12121211122"
j := len(s)
for i := 0; i < 3 && j > 0; i++ {
    _, size := utf8.DecodeLastRuneInString(s[:j])
    j -= size
}
lastByRune := s[j:]

You can also convert the string to a []rune and operate on the rune slice, but that allocates memory.

Simon Fox
  • 5,995
  • 1
  • 18
  • 22