将不同类型的变量通过引用作为参数传递给相同的可变参数

huangapple go评论76阅读模式
英文:

Passing variables of different types by reference as arguments to same variadic parameter

问题

我一直在为golang缺乏可选参数而苦恼,所以我一直在使用最接近的解决方法:可变参数。尽管我已经让它工作了,但是尝试通过引用将多个变量类型传递给同一个可变参数仍然很混乱:

// 后端
func UpdateRef(variadic ...*interface{}) {
	for _, v := range variadic {
		if v.(type) == string {
			*v = "New ref val"
		}
	}
}

// 前端
func Interface(x interface{}) interface{} { return &x }
func main() {
	ref := Interface("Hey") // 初始值为 "Hey"
	i := Interface(500)
    UpdateRef(&ref, &i) // 最终值为 "New ref val"
}

如果我用以下代码替换前端部分:

// 前端
func main() {
	ref := "Hey" // 初始值为 "Hey"
    UpdateRef(ref, 500) // 最终值为 "New ref val"
}

...那么我应该如何更改后端代码才能使期望的前端代码正常工作?后端可以尽可能冗长,只要期望的前端代码保持不变即可。这种可能吗?如果不行,是否有一种优雅的解决方案,可以对期望的前端代码进行最小的更改?

英文:

I've been struggling with golang's lack of optional parameters, so I have been using the closest workaround: variadics. Even though I got it working, it is messy attempting to pass multiple variable types to the same variadic parameter by reference:

// back-end
func UpdateRef(variadic ...*interface{}) {
	for _, v := range variadic {
		if v.(type) == string {
			*v = "New ref val"
		}
	}
}

// front-end
func Interface(x interface{}) interface{} { return &x }
func main() {
	ref := Interface("Hey") // starts as "Hey"
	i := Interface(500)
    UpdateRef(&ref, &i) // ends at "New ref val"
}

If I replace the front-end with this:

// front-end
func main() {
	ref := "Hey" // starts as "Hey"
    UpdateRef(ref, 500) // ends at "New ref val"
}

...then how could I change the back-end to make the desired front-end code work? The back-end can be as verbose as need be, so long as the desired front-end runs as is. Is this possible? If not, is there an elegant solution that requires minimal changes to the desired front-end?

答案1

得分: 3

使用interface{}作为参数类型。使用类型断言转换为指针类型。
解引用指针来设置值。

func UpdateRef(variadic ...interface{}) {
    for _, v := range variadic {
        if v, ok := v.(*string); ok {
            *v = "New ref val"
        }
    }
}

传递指针给函数

ref := "Hey"
i := 500
UpdateRef(&ref, &i)
fmt.Println(ref)  // 输出 "New ref val"
英文:

Use interface{} as the argument type. Type assert to pointer types.
Dereference pointers to set the values.

func UpdateRef(variadic ...interface{}) {
	for _, v := range variadic {
		if v, ok := v.(*string); ok {
			*v = "New ref val"
		}
	}
}

Pass pointers to the function:

ref := "Hey"
i := 500
UpdateRef(&ref, &i)
fmt.Println(ref)  // prints “New ref val”

答案2

得分: 2

你只需要翻译代码部分,以下是翻译好的代码:

package main

import (
	"reflect"
)

// 后端
func UpdateRef(variadic ...interface{}) {
	for _, v := range variadic {
		kind := reflect.TypeOf(v).Kind()
		if kind == reflect.Pointer {
			reflect.ValueOf(v).Elem().Set(reflect.ValueOf("新引用值"))
		}
	}
}

// 前端
func main() {
	ref := "嘿"         // 初始值为 "嘿"
    // 要修改反射对象,值必须是可设置的。
	UpdateRef(&ref, 500) // 结果为 "新引用值"
	println(ref)
}

请查看Golang博客:https://go.dev/blog/laws-of-reflection。

编码愉快!

英文:

you just

package main

import (
	"reflect"
)

// back-end
func UpdateRef(variadic ...interface{}) {
	for _, v := range variadic {
		kind := reflect.TypeOf(v).Kind()
		if kind == reflect.Pointer {
			reflect.ValueOf(v).Elem().Set(reflect.ValueOf("New ref val"))
		}
	}
}

// front-end
func main() {
	ref := "Hey"         // starts as "Hey"
    // To modify a reflection object, the value must be settable.
	UpdateRef(&ref, 500) // ends at "New ref val"
	println(ref)
}

check out the golang blog:https://go.dev/blog/laws-of-reflection.

Coding Happy!

huangapple
  • 本文由 发表于 2022年6月25日 08:23:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/72750480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定