Comment convertir une interface{} qui est vraiment une tranche de types dont le genre est reflect.Int32 en tranche de int32 ?

J'ai ce qui suit:

type Int32A int32
type Int32B int32

et souhaite implémenter une fonction qui peut accepter n'importe quelle tranche de types dont le type est reflect.Int32et le convertir en []int32. Par example:

func ConvertTypeSliceToInt32Slice(es «es-type») []int32 {
result:= make([]int32, len(es))
for i:= 0; i < len(result); i++ {
result[i] = es[i].(int32)
}
return result
}
func caller() {
Int32as:= Int32A{1, 2}
Int32bs:= Int32B{3, 5}
int32as:= ConvertTypeSliceToInt32Slice(Int32as)
int32bs:= ConvertTypeSliceToInt32Slice(Int32bs)
}

Comment cela peut-il être fait avec n'importe quelle définition de type arbitraire dont le genre est reflect.Int32? (Contexte : cette fonction sera utilisée pour convertir des tranches de proto enums ; c'est-à-dire que l'ensemble complet des types est inconnu et illimité, il switchn'est donc pas possible d'effectuer un a sur chaque type).

De plus, j'utilise 1.17donc je ne peux pas utiliser de types paramétrés (alias modèles).

Une tentative qui ne fonctionne pas (ça panique à is.([]interface{})):

func ConvertTypeSliceToInt32Slice(is interface{}) []int32 {
es:= is.([]interface{})
result:= make([]int32, len(es))
for i:= 0; i < len(result); i++ {
result[i] = es[i].(int32)
}
return result
}


Solution du problème

int32dans ce cas est un "type sous-jacent", et ~dans une déclaration de paramètre de type est la façon dont vous spécifiez une contrainte à un type sous-jacent.

Par exemple : https://go.dev/play/p/8-WAu9KlXl5

func ConvertTypeSliceToInt32Slice[T ~int32](es []T) []int32 {
result:= make([]int32, len(es))
for i:= 0; i < len(result); i++ {
result[i] = int32(es[i])
}
return result
}

Si vous avez besoin d'utiliser la réflexion, vous pouvez convertir le type de chaque élément avant de l'ajouter à la tranche finale :

func ConvertTypeSliceToInt32Slice(es interface{}) []int32 {
v:= reflect.ValueOf(es)
int32ty:= reflect.TypeOf(int32(0))
result:= make([]int32, v.Len())
for i:= 0; i < v.Len(); i++ {
result[i] = v.Index(i).Convert(int32ty).Interface().(int32)
}
return result
}

Et si vous devez vous assurer que d'autres types numériques convertibles ne sont pas convertis, vous pouvez comparer le type d'élément et la panique ou l'erreur si nécessaire :

if v.Type().Elem().Kind()!= reflect.Int32 {
...

Commentaires

Posts les plus consultés de ce blog

Erreur Symfony : "Une exception a été levée lors du rendu d'un modèle"

Détecter les appuis sur les touches fléchées en JavaScript

Une chaîne vide donne "Des erreurs ont été détectées dans les arguments de la ligne de commande, veuillez vous assurer que tous les arguments sont correctement définis"