使用任何值类型的映射作为函数参数?

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

using maps with any value type as function parameter?

问题

我正在尝试创建一个函数,该函数以map作为参数,其中map使用string作为键,但值可以是任何类型。

在Go语言中,如何使这个函数正常工作?我尝试使用map[string]interface{}作为函数的参数类型,但是当将map[string]int作为参数传递时,似乎不起作用。

请解释一下这种方法的问题所在,以及是否有办法在Go语言中实现这个目标?

英文:

I am trying to create a function which takes in a map as a parameter, where the map uses string keys but the values can be ANY type.

How do I make this work in go? I tried using map[string]interface{} as the parameter type to the function but that does not seem to work for example when passing in a map[string]int as an argument.

Any explanations as to what is the problem with this approach and if there is a way to achieve this in go?

答案1

得分: 2

如果一个函数参数的类型是map[string]interface{},那么你需要传递一个map[string]interface{}(而map[string]int不是map[string]interface{})。

这是一个常见的问题,在常见问题解答中有详细介绍(该链接主要涉及切片,但同样适用于映射)。

最佳的方法取决于你想要实现什么。你可以像下面这样做(playground):

package main

import (
	"fmt"
)

func main() {
	v := make(map[string]interface{})

	v["blah"] = 3
	test(v)

	v["panic"] = "string"
	test(v)

}

func test(in map[string]interface{}) {
	var ok bool
	converted := make(map[string]int)
	for k, v := range in {
		converted[k], ok = v.(int)
		if !ok {
			panic("Unexpected type in map")
		}
	}
	fmt.Println(converted)
}

或者接受一个interface{},允许传入任何类型的值(playground):

package main

import (
	"fmt"
)

func main() {
	v := make(map[string]int)
	v["blah"] = 3
	test(v)

	w := make(map[string]string)
	w["next"] = "string"
	test(w)

	x := make(map[string]bool)
	x["panic"] = true
	test(x)

}

func test(in interface{}) {
	switch z := in.(type) {
	case map[string]int:
		fmt.Printf("dealing with map[string]int: %v\n", z)
	case map[string]string:
		fmt.Printf("dealing with map[string]string: %v\n", z)
	default:
		panic(fmt.Sprintf("unsupported type: %T", z))
	}
	// You could also use reflection here...
}
英文:

If a function parameter is of type map[string]interface{} then you need to pass it a map[string]interface{} (and map[string]int is not map[string]interface{}).

This is a common issue and is covered in the FAQ (this focuses on slices but the same principal applies to maps).

The best approach really depends upon what you are trying to accomplish. You can do something like the following (playground):

package main

import (
	"fmt"
)

func main() {
	v := make(map[string]interface{})

	v["blah"] = 3
	test(v)

	v["panic"] = "string"
	test(v)

}

func test(in map[string]interface{}) {
	var ok bool
	converted := make(map[string]int)
	for k, v := range in {
		converted[k], ok = v.(int)
		if !ok {
			panic("Unexpected type in map")
		}
	}
	fmt.Println(converted)
}

or accept an interface{} which allows anything to be passed in (playground):

package main

import (
	"fmt"
)

func main() {
	v := make(map[string]int)
	v["blah"] = 3
	test(v)

	w := make(map[string]string)
	w["next"] = "string"
	test(w)

	x := make(map[string]bool)
	x["panic"] = true
	test(x)

}

func test(in interface{}) {
	switch z := in.(type) {
	case map[string]int:
		fmt.Printf("dealing with map[string]int: %v\n", z)
	case map[string]string:
		fmt.Printf("dealing with map[string]string: %v\n", z)
	default:
		panic(fmt.Sprintf("unsupported type: %T", z))
	}
	// You could also use reflection here...
}

huangapple
  • 本文由 发表于 2021年10月21日 07:27:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/69654128.html
匿名

发表评论

匿名网友

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

确定