需要帮助来了解Go中的map_String类型的行为

Please have a look at this code:

package activity

import (
    "fmt"
    "strconv"
    "time"
)

type Activity struct {
    yearContributions map[string]weekContributions
}

type dayContributions struct {
    Date         time.Time
    Contribution int
}

type weekContributions struct {
    Notation string
    AllDays  []dayContributions
}

func (currentWeekContribution *weekContributions) addContribution(additionalDayContribution dayContributions) {
    currentWeekContribution.AllDays = append(currentWeekContribution.AllDays, additionalDayContribution)
}

func (currentActivity *Activity) restore() {
    currentActivity.yearContributions = map[string]weekContributions{
        "Sunday":    weekContributions{Notation: "S", AllDays: make([]dayContributions, 0)},
        "Monday":    weekContributions{Notation: "M", AllDays: make([]dayContributions, 0)},
        "Tuesday":   weekContributions{Notation: "T", AllDays: make([]dayContributions, 0)},
        "Wednesday": weekContributions{Notation: "W", AllDays: make([]dayContributions, 0)},
        "Thursday":  weekContributions{Notation: "T", AllDays: make([]dayContributions, 0)},
        "Friday":    weekContributions{Notation: "F", AllDays: make([]dayContributions, 0)},
        "Saturday":  weekContributions{Notation: "S", AllDays: make([]dayContributions, 0)},
    }
}

func (currentActivity *Activity) Recalibrate() {
    currentActivity.restore()

    endDate := time.Now().UTC()
    startDate := endDate.AddDate(-1, 0, 0)

    for d := startDate; endDate.After(d); d = d.AddDate(0, 0, 1) {
        stringWeekday := d.Weekday().String()
        currentWeekContribution := currentActivity.yearContributions[stringWeekday]
        currentWeekContribution.addContribution(dayContributions{Date: d, Contribution: 1})
        fmt.Println(currentWeekContribution) // prints : {T [{2017-01-26 09:39:45.711238257 +0000 UTC 1}]}
    }
    fmt.Println(currentActivity.yearContributions) // prints : map[Tuesday:{T []} Wednesday:{W []} Thursday:{T []} Friday:{F []} Saturday:{S []} Sunday:{S []} Monday:{M []}]
}

func (singleDayContribution dayContributions) ReadableDate() string {
    singleDate := singleDayContribution.Date
    return singleDate.Month().String() + " " + strconv.Itoa(singleDate.Day()) + ", " + strconv.Itoa(singleDate.Year())
}

func (currentActivity Activity) GetContributionsForYear() map[string]weekContributions {
    return currentActivity.yearContributions
}

I am trying to append new dayContributions to the array weekContributions.AllDays. currentWeekContribution.AllDays = append(currentWeekContribution.AllDays, additionalDayContribution) is the part appends to the AllDays property of the current type weekContributions.

The print statement prints the weekContributions array with a single member in the array. But the following print function says that all map values i.e. weekContributions objects have empty arrays as AllDays property.

My aim - To append dayContribution objects to values in map activity.yearContributions

I think -

  1. The append function is working as intended as it appends 1 member on each iteration
  2. Somehow, the currentWeekContribution.addContribution line [Line 48] is only appending to the local variable currentWeekContribution and doesn't update the corresponding value in currentActivity.yearContributions map

I am very new to golang and I think I am not following the go way / this would have worked in java or ruby I don't know what this behaviour is called, so can't google search anything relevant.

Two way you can do this.

One, You need to use pointer in as Map value. So that when you are appending in your local variable, you are changing through reference.

type Activity struct {
    yearContributions map[string]*weekContributions
}

type dayContributions struct {
    Date         time.Time
    Contribution int
}

type weekContributions struct {
    Notation string
    AllDays  []*dayContributions
}

Two, When you are doing following

currentWeekContribution := currentActivity.yearContributions[stringWeekday]

You are assigning a local variable. And you are appending to it. Now, you need to reassign that local variable. Like

currentWeekContribution := currentActivity.yearContributions[stringWeekday]
currentWeekContribution.addContribution(dayContributions{Date: d, Contribution: 1})
currentActivity.yearContributions[stringWeekday]= currentWeekContribution