Как преобразовать срез в массив?

Я хочу реализовать метод для преобразования interface{} нарезать interface{} массив, длина которого равна заданному срезу. Это похоже на ниже:

func SliceToArray(in []interface{}) (out interface{}) {
 ...
}
// out's type is [...]interface{} and len(out)==len(in)

Как я могу реализовать этот метод?

РЕДАКТИРОВАТЬ: любой возможный для использования reflect.ArrayOf реализовать это?

2 ответа

Решение

Используйте refle.ArrayOf для создания типа массива с учетом типа элемента среза. Используйте рефлекс.Нью для создания значения этого типа. Используйте рефлектограмму для копирования из среза в массив.

func SliceToArray(in interface{}) interface{} {
    s := reflect.ValueOf(in)
    if s.Kind() != reflect.Slice {
        panic("not a slice")
    }
    t := reflect.ArrayOf(s.Len(), s.Type().Elem())
    a := reflect.New(t).Elem()
    reflect.Copy(a, s)
    return a.Interface()
}

Запустите его на детской площадке

Эта функция полезна для создания ключа карты из среза и других сценариев, где требуется сопоставимое значение. В противном случае обычно лучше использовать срез, когда длина может быть произвольной.

Go 1.20 (1 квартал 2023 г.) должен облегчить такое преобразование после проблемы 46505: «спецификация: разрешить преобразование из среза в массив»

Это решается с помощью CL 430415, 428938 ( type), 430475 ( reflect) и 429315 ( spec)

Преобразования из среза в массив или указатель массива

Преобразование среза в массив дает массив, содержащий элементы базового массива среза.

Точно так же преобразование среза в указатель массива дает указатель на базовый массив среза.

В обоих случаях, если длина среза меньше длины массива, возникает паника во время выполнения .

      s := make([]byte, 2, 4)

a0 := ([0]byte)(s)
a1 := ([1]byte)(s[1:])   // a1[0] == s[1]
a2 := ([2]byte)(s)       // a2[0] == s[0]
a4 := ([4]byte)(s)       // panics: len([4]byte) > len(s)
Другие вопросы по тегам