2017-10-21 2 views
2

를 사용하여 구조체의 슬라이스 필드에 나는이처럼 보이는 struct 있습니다 추가] 반사

type guitaristT struct { 
    Surname string `required=true` 
    Year  int64 `required=false` 
    American bool  // example of missing tag 
    Rating float32 `required=true` 
    Styles []string `required=true,minsize=1` 
} 

나는 다음과 같은 환경 변수를 가지고, 그리고 나는 구조체를 채우기 위해 반사를 사용하고 있습니다 키를 기반으로합니다.

jimiEnvvar :="surname=Hendrix|year=1942|american=true|rating=9.99 
    |styles=blues|styles=rock|styles=psychedelic" 

나는 반사를 사용하여 string, int64, bool and float32 필드를 설정할 수 있어요,하지만 난 slice 필드 스타일에 추가하는 방법에 갇혔어요. 예를 들어 위의 jimiEnvvar을 기준으로 jimi.Styles 필드의 값은 ["blues","rock", "psychedelic"]입니다.

I 다음 간체 코드 가지고

result := guitaristT{} 
// result.Styles = make([]string, 10) // XXX causes 10 empty strings at start 
result.Styles = make([]string, 0)  // EDIT: Alessandro's solution 
... 
v := reflect.ValueOf(&result).Elem() 
... 
field := v.FieldByName(key) // eg key = "styles" 
... 
switch field.Kind() { 

case reflect.Slice: 
    // this is where I get stuck 
    // 
    // reflect.Append() has signature: 
    // func Append(s Value, x ...Value) Value 

    // so I convert my value to a reflect.Value 
    stringValue := reflect.ValueOf(value) // eg value = "blues" 

    // field = reflect.Append(field, stringValue) // XXX doesn't append 
    field.Set(reflect.Append(field, stringValue)) // EDIT: Alessandro's solution 

EDIT (I 해결할)

제 2 부분은 구조체에지도를 작성 하였다. 예를 들면 :

type guitaristT struct { 
    ... 
    Styles []string `required=true,minsize=1` 
    Cities map[string]int 
} 
처럼 jimiEnvvar 보이는

:

case reflect.Map: 
     fmt.Println("keyAsString", keyAsString, "is Map, has value:", valueAsString) 
     mapKV := strings.Split(valueAsString, "^") 
     if len(mapKV) != 2 { 
      log.Fatalln("malformed map key/value:", mapKV) 
     } 
     mapK := mapKV[0] 
     mapV := mapKV[1] 
     thisMap := fieldAsValue.Interface().(map[string]int) 
     thisMap[mapK] = atoi(mapV) 
     thisMapAsValue := reflect.ValueOf(thisMap) 
     fieldAsValue.Set(thisMapAsValue) 

The final result was: 

main.guitaristT{ 
    Surname: "Hendrix", 
    Year:  1942, 
    American: true, 
    Rating: 9.989999771118164, 
    Styles: {"blues", "rock", "psychedelic"}, 
    Cities: {"London":11, "Bay Area":9, "New York":17, "Los Angeles":14}, 
} 

:이 방식으로 쓴

jimiEnvvar += "|cities=New York^17|cities=Los Angeles^14" 

관심이 있으시면 전체 코드는 https://github.com/soniah/reflect/blob/master/structs.go입니다. 코드는 내가 쓰고있는 몇 가지 노트/연습입니다.


EDIT2 :의

제 11 장 "연습에 가서"(백정과 곡식 가루)을 반영, 구조체 및 태그에 대한 설명을 자세히 설명하고있다.

답변

1

너무 멀지 않았습니다.

field.Set(reflect.Append(field, stringValue)) 

으로 바꾸면 완료됩니다. 또한, 당신이

result.Styles = make([]string, 0) 

를 사용하여 슬라이스를 초기화해야 당신을하거나 Styles 배열의 상단 (10) 빈 문자열을 가진 종료됩니다.

희망이 있으면 프로젝트에 도움이되고 행운이 있기를 바랍니다.

+0

답변 주셔서 감사합니다. Alessandro. 오늘 나는 맵 코드에 대해 작업했다. 작동하지만 어쩌면 개선에 대한 의견이있을 수 있습니까? –