#string #go
#строка #Вперед
Вопрос:
В go у нас есть strings.Builder
возможность добавлять символы, которая лучше, чем использование s = s string(character)
, но как насчет того, есть ли оптимальный способ удалить последний символ вместо s = s[:len(s)-sizeOfLastCharacter]
?
Комментарии:
1. Обратите внимание, что подобное использование нарезки вызовет проблемы, когда строка содержит символы, которые занимают более 1 байта. play.golang.org/p/_017wGYNfa4
Ответ №1:
Нарезка — очень эффективная операция, как подробно описано во внутренних элементах среза:
Нарезка не копирует данные фрагмента. Это создает новое значение фрагмента, которое указывает на исходный массив. Это делает операции срезов такими же эффективными, как манипулирование индексами массива.
По сути, удаление последнего элемента фрагмента означает создание нового дескриптора фрагмента, указывающего на тот же массив, но меньшей длины. За исключением прямого доступа к внутренним элементам фрагмента, вы не найдете более эффективного решения.
Комментарии:
1. Что, если у меня есть stringsBuilder, тогда я хочу удалить его последний символ, в этом случае я не могу использовать нарезку в stringsBuilder, так как мне следует подойти?
2. Вы не можете, для эффективного добавления используется конструктор, вы не можете обрезать базовый фрагмент байта. Лучшее, что вы можете сделать, это усечь выходные данные
b.String()
, но это не изменит конструктор.
Ответ №2:
Используйте utf8.DecodeLastRuneInString()
, чтобы узнать, сколько байтов «занимает» последняя руна, и срезать исходную строку на основе этого. Сокращение string
приводит к string
значению, которое разделяет резервный массив с оригиналом, поэтому string
содержимое не копируется, создается только новый заголовок строки, который состоит всего из 2 целых значений (см. reflect.StringHeader
).
Например:
s := "Hello, 世界"
r, size := utf8.DecodeLastRuneInString(s)
if r != utf8.RuneError {
s = s[:len(s)-size]
}
fmt.Println(s)
Выходные данные (попробуйте это на игровой площадке Go):
Hello, 世