Golang:每个键对应多个值的映射

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

Golang: map with multiple values per key

问题

func ParseportsFromFile(file string) (map[string][]string, error) {
	buf, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	ret := make(map[string][]string)
	rows := strings.Split(string(buf), "\n")
	for _, row := range rows {
		kvs := strings.SplitN(row, "=", 2)
		if len(kvs) == 2 {
			key := strings.TrimSpace(kvs[0])
			value := strings.TrimSpace(kvs[1])
			ret[key] = append(ret[key], value)
		}
	}
	return ret, nil
}

这个函数允许我读取一个文件,文件内容如下:

user1=123
user1=321
user2=124

然而,返回的数据是:

map[user1:[321] user2:[124]]

这意味着user1=123user1=321覆盖了。如何避免这种情况发生?如何创建一个类似于map[user1:[123,321], user2:124]的数组,以避免一个项目覆盖另一个项目?

英文:

 func ParseportsFromFile(file string) (map[string]string, error) {
        	buf, err := ioutil.ReadFile(file)
        	if err != nil {
        		return nil, err
        	}
        	ret := [make(map[string]string)]
        	rows := strings.Split(string(buf), "\n")
        	for _, row := range rows {
        		kvs := strings.SplitN(row, "=", 2)
        		if len(kvs) == 2 {
        			ret[strings.TrimSpace(kvs[0])] = strings.TrimSpace(kvs[1])
        		}
        	}
        	return ret, nil
        }

This function allows me to read a file like that :

user1=123 
user1=321 
user2=124 

However, the data return is

map[user1:321 user2:124]

So that mean user1=123 has been overwritten with user1=321
How to avoid that ?
How to create an array like
map[user1:[123,321], user2: 124]
to avoid an item to overwrite another ?

答案1

得分: 5

由于Go语言是强类型的,所以将其立即转换为切片的映射可能更容易。例如,可以参考http.Header类型。在设计时,他们也面临着同样的问题。

在你的情况下,代码可能如下所示:

result := make(map[string][]string)

for _, row := range rows {
    parts := strings.Split(row, "=")
    key := parts[0]
    value := parts[1]
    result[key] = append(result[key], value)
}

https://go.dev/play/p/5uRH-aQmATR

否则,你需要使用interface{}(任意类型),这样你就可以同时拥有string[]string,但是实现这个逻辑会更复杂,而且使用起来也更复杂,因为你总是需要检查它的类型并进行类型断言等操作。总的来说,我不建议这样做。

英文:

Since go is strongly typed, it would be easier to make it right away a map of slices. See the http.Header type, for example. They had the same problem to solve when designing it.

In your case, this could look something like this:

result := make(map[string][]string)

for _, row := range rows {
	parts := strings.Split(row, "=")
	key := parts[0]
	value := parts[1]
	result[key] = append(result[key], value)
}

https://go.dev/play/p/5uRH-aQmATR

Otherwise, you need to use interface{} (any) so you can have both, string and []string, but the logic to get that done would be more complex, and using it would be also more complex since you always need to check what it is and do type assertion and so on. After all, I would not recommend it.

huangapple
  • 本文由 发表于 2022年5月15日 19:08:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/72247685.html
匿名

发表评论

匿名网友

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

确定