'Golang map[string]float where float is getting overwirtten instead of adding to the existing value present for the key

I have a string like so 00:01:07,400-234-090 00:05:01, 701-080-080 00:05:00, 400-234-090

where the on the right side is the phone number and on the left is the duration of the call in hh:mm:ss format. I am trying to put this in a map[string]float64 by splitting the string first on "," and the split the left side on ":". Then make a Duration from the duration of the call and convert in to minutes. It works fine till this. Now I am trying to put this in a map, I expected that if the key which is the phone number on the right is already present in the map then it will just add the float64 value to the existing value of the key. However, that is not the case, it seems to be having the same key twice in the map.

Here is my code:

phoneBill := `00:01:07,400-234-090
          00:05:01, 701-080-080
          00:05:00, 400-234-090`

callLog := strings.Split(phoneBill, "\n")

mapDetails := make(map[string]float64)
for _, v := range callLog {
    callDetails := strings.Split(strings.TrimSpace(v), ",")
    timeDetails := strings.Split(strings.TrimSpace(callDetails[0]), ":")
    durationString := strings.TrimSpace(timeDetails[0]) + "h" + strings.TrimSpace(timeDetails[1]) + "m" + strings.TrimSpace(timeDetails[2]) + "s"

    t, _ := time.ParseDuration(durationString)

    total := t.Minutes()
    fmt.Printf("phone number is: %v \n", callDetails[1])
    fmt.Printf("duration of call in minutes is %v \n", total)

    if v, found := mapDetails[callDetails[1]]; found {
        total += v
        fmt.Println("total is :v", total)
    }
    mapDetails[(callDetails[1])] = total

}
fmt.Println("Values in map are: %v", mapDetails)

https://go.dev/play/p/fLcEDbgQ-7q



Solution 1:[1]

Fix by trimming spaces on the duration and the number. The current code does not handle spaces before or after the comma.

    i := strings.Index(v, ",")
    if i < 0 {
        log.Fatal("bad line", v)
    }
    dur := strings.TrimSpace(v[:i])
    num := strings.TrimSpace(v[i+1:])

Taking advantage of the fact that maps return the zero value for missing keys, the code to update the map can be simplified to the following.

    mapDetails[num] += total

Run the code on the playground.

When debugging code that parses strings, it's helpful to make whitespace visible by printing with %q. The bug in the original program is more visible with:

    fmt.Printf("phone number is: %q \n", callDetails[1])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1