Я хотел бы передать структуру как ссылку на функцию и в зависимости от ее типа, определенного путем отражения, выполнить соответствующие преобразования и сохранить значение в самой структуре.
ОДНАКО, хотя код выполняется, а значения идентифицируются и преобразуются внутри функции, когда элемент управления возвращается к функции main (), структура не имеет значений, которые я хотел бы сохранить там.
Вот код:
package main
import (
"fmt"
"reflect"
"strconv"
)
type x struct {
f1 string
f2 int
f3 bool
}
func main() {
s := x{}
getData(&s.f1, "AAA")
getData(&s.f2, "1")
getData(&s.f3, "true")
fmt.Println(s)
}
func getData(data interface{}, value string) {
if value != "" {
switch reflect.TypeOf(data).String() {
case "*int":
data, _ = strconv.Atoi(value)
case "*bool":
data, _ = strconv.ParseBool(value)
case "*string":
data = value
}
}
}
В этом примере я получаю { 0 false}
, ожидая { AAA 1 true}
.
Есть ли какой-нибудь Golang GURU, который может сказать мне, что я делаю не так с этим кодом?
Ниже ссылка на детскую площадку https://play.golang.org/p/l1_INJLOhAq
Спасибо, что НЕ помогали @Volker. Хотя ваша точка зрения в какой-то мере верна, люди, которые действительно знают эту вещь, поняли ее с первого раза и мудро потратили свое время на то, чтобы помочь, а не критиковать. Измени свое отношение, товарищ, если не хочешь помочь, передавай ...
Вам нужно использовать reflect.Value.Elem()
, чтобы получить фактическое значение, а не сам указатель.
Вот краткая суть:
func getData(data interface{}, value string) {
switch v := data.(type) {
case *int:
val := reflect.ValueOf(v).Elem()
intVal, _ := strconv.Atoi(value)
val.SetInt(int64(intVal))
}
}
Предлагаю прочитать Законы отражения
Я предлагаю ответ @ ThunderCat, который проще и лучше подходит для вашего варианта использования. В размышлениях действительно нет нужды.
Спасибо weavr. Ваше решение также работает, но действительно то, что опубликовано ThundeCat, мне больше подходит. Спасибо друг
Используйте переключатель типа для выполнения кода в зависимости от типа значения. В этом сценарии нет необходимости использовать отражение.
func getData(data interface{}, value string) {
if value != "" {
switch data := data.(type) {
case *int:
*data, _ = strconv.Atoi(value)
case *bool:
*data, _ = strconv.ParseBool(value)
case *string:
*data = value
}
}
}
Подробнее о переключателях типа: Go Tour, Go Спецификация, Эффективный Go.
Спасибо ThunderCat! Переключатель типа был отсутствующим звеном и причиной, по которой я получал «недопустимый косвенный источник данных (тип интерфейса {})». Спасибо, что поделился
Перестаньте думать об указателе как о «ссылке». Это не так и бесполезно рассматривать указатель как ссылку. (Что бы вы назвали *** int?)