![](/img/trans.png)
[英]How to pass to a function that takes two arguments an element from one list together with each element of another list?
[英]Pass list of one of two structures to the function
Go 中的新功能,找不到任何直观的方法。
我有这样一段代码
tx = getTx()
for _, record := range tx.a {
// do a lot with record.Important
}
for _, record := range tx.b {
// do a lot with record.Important
}
for _, record := range tx.c {
// do a lot with record.Important
}
以及以下结构:
type Record1 struct {
// fields of Record1
Important string
}
type Record2 struct {
// fields of Record1
Important string
}
type TX struct {
a []Record1
b []Record1
c []Record2
}
现在逻辑是将每个for逻辑提取到 function 中:
func helper(records) { // Here is the problem
// do a lot with record.Important
}
问题:
records是[]Record1
或[]Record2
类型。 但看起来 Golang 中不存在 Union 类型。 所以我想我可以将[]string
传递给helper ,但甚至找不到一种优雅的方法来获得相当于map(lambda r: r.Important, tx.a)
的东西。 没有高阶map function,没有list comprehension。 我不相信使用原始for循环来解决这个问题。
跨多种类型进行循环的一种方法是将接口与 generics 一起使用。让每个Record
类型为重要字段实现一个 getter 方法。 然后声明一个接口,在其方法集中包含该 getter 方法。 然后,您可以通过将接口声明为其类型参数来使您的helper
通用。
func (r Record1) GetImportant() string { return r.Important }
func (r Record2) GetImportant() string { return r.Important }
type ImportantGetter interface {
GetImporant() string
}
func helper[T ImportantGetter](s []T) {
for _, v := range s {
_ = v.GetImportant()
}
}
除非我误解了你的问题,否则你似乎想从一组记录中提取 X 列中的所有值,然后将这些值作为切片传递给某个 function - 我的假设基于你希望 go有类似map()
的东西。
如果你追求的是类型不可知论,你当然可以使用mkopriva建议的接口方法,但你不会摆脱使用for
循环 - 列表类型的迭代是惯用语 go 的核心。如果你需要一个映射 function,你将不得不编写一个来执行你想要的映射。
我会注意到你不需要 generics 来做mkopriva建议的事情,你可以只使用一个界面而不用 generics go playground混淆水域:
package main
import "fmt"
type Record1 struct {
Important string
}
type Record2 struct {
Important string
}
func (r Record1) GetImportant() string { return r.Important }
func (r Record2) GetImportant() string { return r.Important }
type ImportantGetter interface {
GetImportant() string
}
func helper(s []ImportantGetter) {
for _, v := range s {
fmt.Println(v.GetImportant())
}
}
func main() {
records := []ImportantGetter{Record1{Important: "foo"}, Record2{Important: "bar"}}
helper(records)
}
另一种类型不可知论的方法,以及“我希望所有这些类型都有一个共同的属性”的惯用方法(恕我直言)是使用struct
嵌入和类型断言来构建您自己的Map()
function go 操场:
type CommonFields struct {
Important string
}
type Record1 struct {
CommonFields
FieldSpecificToRecord1 string
}
type Record2 struct {
CommonFields
FieldSpecificToRecord2 int
}
func main() {
r1 := Record1{
CommonFields{Important: "I'm r1!"},
"foo",
}
r2 := Record2{
CommonFields{Important: "I'm r2!"},
5,
}
records := []interface{}{r1, r2, "this is not a valid record type"}
fmt.Println(Map(records))
}
func Map(source []interface{}) []string {
destination := make([]string, len(source))
for i, sourceRecord := range source {
if rr, ok := sourceRecord.(Record1); ok {
destination[i] = rr.Important
} else if rr, ok := sourceRecord.(Record2); ok {
destination[i] = rr.Important
} else {
destination[i] = "undefined"
}
}
return destination
}
您可能想让Map()
的实现接受一个参数,该参数指定要提取的字段以符合您在其他语言中的内容,或者甚至可能只是传入一个助手 function 来完成大部分特定于类型的值提取.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.