str:=string(bytes_array[:]);
Скоро выяснилось, что это плохо с точки зрения производительности: для переменной str будет выделена новая область памяти, куда будет скопировано всё содержимое bytes_array. Если объем данных значителен или одновременно выполняется множество goroutines, то выполнение ощутимо замедляется (в моём случае среднее время обработки запроса увеличивалось почти на 100 мс). Возник вопрос: можно ли как-то преобразовать массив без копирования. После недолгих поисков в Интернете нашлось решение, реализованное через небезопасную работу с указателями:
func bytesToString(b []byte) string {
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b));
sh := reflect.StringHeader{bh.Data, bh.Len};
return *(*string)(unsafe.Pointer(&sh));
}
str:=bytesToString(bytes_array);
Работает этот код так: берет указатель на заголовок slice, извлекает из него длину и указатель на данные, и записывает в аналогичную структуру для строки, а потом возвращает её из функции. Для того, чтобы код скомпилировался, нужно в import указать "reflect" и "unsafe".