Is there a nice way to get length of slice elem in map regardless of its concrete type?

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

Is there a nice way to get length of slice elem in map regardless of its concrete type?

问题

例如,我有两个映射,分别是 map[string][]structAmap[string][]int

我想要遍历这个映射并打印出每个切片的长度,我能在一个函数中实现这个吗?

我尝试定义一个接口,并在两种类型的切片中实现它,但是编译器无法进行类型转换。

type Container interface{
    Len() int
}

type Slice1 []int
func (s Slice1) Len() int {
    return len(s)
}

type Slice2 []StructA
func (s Slice2) Len() int {
    return len(s)
}

func iterate(input map[string]Container) {
    for key, value := range input {
        log.Printf("key:%s, length:%d", key, value.Len())
    }
}

func main() {
    // 无法进行类型转换
    iterate(map[string]Slice1{})
    iterate(map[string]Slice2{})
}
英文:

For example, I have two maps, namely map[string][]structAand map[string][]int.

I want to iterate the map and print out length of every slice, can I implement this in a single function?

I tried to define an interface and implement it in two kinds of slices, but the compiler just cannot do the type cast.

type Container interface{
    Len() int
}

type Slice1 []int
func (s Slice1) Len() int {
    return len(s)
}

type Slice2 []StructA
func (s Slice2) Len() int {
    return len(s)
}

func iterate(input map[string]Container) {
    for key, value := range input {
        log.Printf("key:%s, lenght:%d", key, value.Len())
    }
}

func main() {
    // cannot do the type cast
    iterate(map[string]Slice1{})
    iterate(map[string]Slice2{})
}

答案1

得分: 1

你可以将这个功能实现在一个单独的函数中,但是调用函数的方式需要做一些改变。将你的映射转换为map[string]Container,然后调用iterate函数。

func main() {
	// 无法进行类型转换
	map1 := map[string][]int{
		`key`: []int{1,2,3},
	}

	map1Container := make(map[string]Container)
	for key, value := range map1 {
		map1Container[key] = Slice1(value)
	}

	map2 := map[string][]StructA{
		`key1`: []StructA{{}, {}},
	}
	map2Container := make(map[string]Container)
	for key, value := range map2 {
		map2Container[key] = Slice2(value)
	}

	iterate(map1Container)
	iterate(map2Container)
}

输出:

2021/07/06 12:15:25 key:key, length:3
2021/07/06 12:15:25 key:key1, length:2

iterate函数期望接收map[string]Container类型的参数。因此,你可以使用Container类型初始化它,并在映射的不同键中包含不同的Container实现。

func main() {
	// 无法进行类型转换
	iterate(map[string]Container{
		`ke1`: Slice1([]int{
			1, 2, 3,
		}),
		`ke2`: Slice2([]StructA{
			{},
			{},
		}),
	})
}

输出:

2021/07/06 11:57:55 key:ke1, length:3
2021/07/06 11:57:55 key:ke2, length:2
英文:

"can I implement this in a single function?"

Yes, but the way you called the function should be changed. Convert your maps to map[string]Container and then call the iterate

func main() {
	// cannot do the type cast
	map1 := map[string][]int{
		`key`: []int{1,2,3},
	}

	map1Container := make(map[string]Container)
	for key, value := range map1 {
		map1Container[key] = Slice1(value)
	}

	map2 := map[string][]StructA{
		`key1`: []StructA{{}, {}},
	}
	map2Container := make(map[string]Container)
	for key, value := range map2 {
		map2Container[key] = Slice2(value)
	}

	iterate(map1Container)
	iterate(map2Container)
}

Output:

2021/07/06 12:15:25 key:key, lenght:3
2021/07/06 12:15:25 key:key1, lenght:2

iterate function expected map[string]Container type parameter. So you can initiate that with Container type and inside the map with different keys, you can include different Container's implementations.

func main() {
	// cannot do the type cast
	iterate(map[string]Container{
		`ke1`: Slice1([]int{
			1, 2, 3,
		}),
		`ke2`: Slice2([]StructA{
			{},
			{},
		}),
	})
}

Output:

2021/07/06 11:57:55 key:ke1, lenght:3
2021/07/06 11:57:55 key:ke2, lenght:2

huangapple
  • 本文由 发表于 2021年7月6日 14:13:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/68265409.html
匿名

发表评论

匿名网友

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

确定