具有以下代码:
func MakeMap(fpt interface{}) {
fnV := reflect.ValueOf(fpt).Elem()
fnI := reflect.MakeFunc(fnV.Type(), implMap)
fnV.Set(fnI)
}
func implMap(in []reflect.Value) (retSlc []reflect.Value) {
fun := in[0] // Function to be applied to each of string elems
str := in[1] // Passed string
// Prepare for creating new result string as strings in go are immutable.
var builder strings.Builder
builder.Grow(str.Len())
// Convert string to slice of runes for utf-8 compatibility.
extractedString := []rune(str.String())
// Iterate over all runes in string and apply passed function to each.
for i := 0; i < len(extractedString); i++ {
// reflect.Value.Call expects slice of reflect.Values so we pack it
// into one.
replaceWrapper := []reflect.Value{reflect.ValueOf(extractedString[i])}
// As return value is also slice of reflect.Value's, we extract
// only expected element by [0]
replaceVal := fun.Call(replaceWrapper)[0]
builder.WriteRune(replaceVal.Interface().(rune))
}
// ##################
// PANIC - panic: reflect: reflect.flag.mustBeAssignable using unaddressable value
str.SetString(builder.String())
// Tried:
// - creating temporary value,
// - retStr := reflect.New(reflect.TypeOf(builder.String())), but still cannot use Set()
// ##################
retSlc = []reflect.Value{str}
return
}
func main() {
var fun func(func(s rune) rune, string) string
MakeMap(&fun)
str := "data_人生ってなに_пустота"
fun(func(s rune) rune {
return s + 1
}, str)
fmt.Println(str)
}
我遇到了一种全新的野兽,尽管我努力理解根据C / C ++的习惯,golang中的可分配性仍然是个谜。
if CanSet() is false.A Value can be changed only if it is addressable and was not obtained by the use of unexported struct fields
[This great article向我解释了很多有关go中的可寻址性,尽管我仍然不确定上面示例中的恐慌如何优雅地解决以及在golang中堆栈和堆如何工作。