使代码更通用

I have a program where many functionalities are similar across different structures, however, I end up writing these functions again and again, esp because the variable that are being dealt inside are of different structures.

I have written a sample code here.

In Go Playgroud

package main

import "fmt"

func (a *Match) Add(v Match) {
    a.Runs += v.Runs
    a.Points += v.Points
}

type Match struct {
    Runs   uint64
    Points uint64
}

func (a *Activity) Add(v Activity) {
    a.Walk += v.Walk
    a.Jog += v.Jog
}

type Activity struct {
    Walk uint64
    Jog  uint64
}

func GetDailyMatches() map[string]Match {
    var dailyMatches map[string]Match

    Match1, Match2 := Match{5, 10}, Match{1, 2}
    dailyMatches = make(map[string]Match)
    dailyMatches["01"] = Match1
    dailyMatches["02"] = Match2
    dailyMatches["03"] = Match1
    dailyMatches["04"] = Match2
    return dailyMatches
}

func GetDailyActivities() map[string]Activity {
    var dailyActivities map[string]Activity

    Activity1, Activity2 := Activity{5, 10}, Activity{1, 2}
    dailyActivities = make(map[string]Activity)
    dailyActivities["01"] = Activity1
    dailyActivities["02"] = Activity2
    dailyActivities["03"] = Activity1
    dailyActivities["04"] = Activity2
    return dailyActivities
}

func main() {
    fmt.Println(CalculateMatchSummary("01", "03"))
    fmt.Println(CalculateActivitySummary("02", "04"))
    fmt.Println(CalculateMatchSummary("01", "03"))
    fmt.Println(CalculateActivitySummary("02", "04"))
}

func CalculateMatchSummary(start, end string) (total Match) {
    dailyMatches := GetDailyMatches()
    for day, value := range dailyMatches {
        if day < start {
            continue
        } else if day > end {
            continue
        } else {
            total.Add(value)
        }
    }
    return
}

func CalculateActivitySummary(start, end string) (total Activity) {
    dailyActivities := GetDailyActivities()
    for day, value := range dailyActivities {
        if day < start {
            continue
        } else if day > end {
            continue
        } else {
            total.Add(value)
        }
    }
    return
}

If you notice, both Match and Activity has the same functions and same structures, except that internally they are of different structures.

Is there a easy way to make the code more generic (Go generics, which is not there in Go??) in Golang itself.

Go has a pretty package "reflect". You can not do genericity strictly speaking but you can get unification of code for the same behavior. I've changed your playground a bit : https://play.golang.org/p/bfqZsFOgVQ

The main part :

func AddTwo(a, b interface{}) interface{} {
    va := reflect.ValueOf(a)
    vb := reflect.ValueOf(b)
    res := reflect.New(reflect.TypeOf(a)).Elem()
    if va.Kind() != reflect.Struct && vb.Kind() != reflect.Struct {
        return nil
    }

    na, nb := va.NumField(), vb.NumField()
    if na != nb {
        return nil
    }

    for i := 0; i < na; i++ {
        // additional verification needed here
        fa := va.Field(i).Uint()
        fb := vb.Field(i).Uint()
        fr := fa + fb
        res.Field(i).SetUint(fr)
    }

    return res.Interface()
}

I use reflect to check the fields of the struct I am given. If both are uint64, I can add them reflectively. If your structs contains many uint64, it can add them all !

Note that you must convert the resulting interface to the type of the struct given after calling this function. That is why this is not strictly generic, because the returning type is a interface, and not a Match or Activity.

EDIT: No need even to return a new struct. You can simply update the field of the "a" struct by calling .SetUint() method.