Как преобразовать срез в массив?
Я хочу реализовать метод для преобразования 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)