Go 通过reflect.Value.SetString设置新字符串
具有以下代码:Go 通过reflect.Value.SetString设置新字符串,go,Go,具有以下代码: 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
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)
}
func MakeMap(fpt接口{}){
fnV:=reflect.ValueOf(fpt).Elem()
fnI:=reflect.MakeFunc(fnV.Type(),implMap)
fnV.Set(fnI)
}
func implMap(在[]reflect.Value中)(retSlc[]reflect.Value){
fun:=in[0]//要应用于每个字符串元素的函数
str:=in[1]//传递的字符串
//准备创建新的结果字符串,因为go中的字符串是不可变的。
var builder strings.builder
builder.Grow(str.Len())
//将字符串转换为符文片段以实现utf-8兼容性。
extractedString:=[]符文(str.String())
//迭代字符串中的所有符文,并对每个符文应用传递的函数。
对于i:=0;i
我遇到了一头全新的野兽,尽管我努力去理解自然法则
在使用C/C++之后,golang中的可分配性仍然很神秘
从golang docs:我们可以看到,如果CanSet()为false,它将陷入恐慌。
其中,在CanSet()中,只有当值可寻址且不是通过使用未报告的结构字段获得时,才可以更改该值
向我解释了很多关于go中的可寻址性的内容,尽管我仍然不确定上面示例中的恐慌是如何优雅地解决的,以及堆栈和堆在go中是如何工作的。看起来生成的函数旨在返回修改后的字符串。鉴于此,main
函数的结尾应该如下所示:
str2 := fun(func(s rune) rune {
return s + 1
}, str)
fmt.Println(str2)
返回新的sting值,而不是修改生成的函数参数。函数参数不可设置
func implMap(in []reflect.Value) []reflect.Value {
fun := in[0] // Function to be applied to each of string elems
str := in[1] // Passed string
var builder strings.Builder
builder.Grow(str.Len())
extractedString := []rune(str.String())
for i := 0; i < len(extractedString); i++ {
replaceWrapper := []reflect.Value{reflect.ValueOf(extractedString[i])}
replaceVal := fun.Call(replaceWrapper)[0]
builder.WriteRune(replaceVal.Interface().(rune))
}
// Previous lines are same as before (without comments).
// Return result with reflect.Value from builder's string.
retStr := reflect.ValueOf(builder.String())
return []reflect.Value{retStr}
}
通过使用字符串简化所有这些。直接映射:
str := "data_人生ってなに_пустота"
str2 := strings.Map(func(s rune) rune { return s + 1 }, str)
fmt.Println(str2)
func MakeMap(fn *func(func(s rune) rune, string) string) {
*fn = func(mapping func(rune) rune, s string) string {
return strings.Map(mapping, s)
}
}
str := "data_人生ってなに_пустота"
str2 := strings.Map(func(s rune) rune { return s + 1 }, str)
fmt.Println(str2)