In my previous [question][1] I asked how could the Redis client be improved.
Here I will ask how can the Game data Client can be improved. Game Data client sits on top of Redis Client and uses datatypes from datape package

Here is the code:

    package gamedatamanager


    import (
        "log"
        "reflect"
        "encoding/json"
        "sort"

        "gogameserver/util"
        dt  "gogameserver/datatypes" 
        rcl "gogameserver/redisclient" 
    )

    const REDIS_NIL string  = "redis: nil"

    type GameManager struct {
        rc *rcl.RedisClient
    }

    func New() (gm * GameManager) {
        return &GameManager{
            rc: rcl.New(),
        }
    }

    func (gm * GameManager) DelKey(key string) (int64, bool) {
        redisRet, err := gm.rc.DelKey(key)
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("\nERROR:DelKey| Key: %s not found, err:%v", key, err)
            return -1, false
        } else {
            return redisRet, true
        }
    }

    func (gm * GameManager) GetPlayerData(gameName string, playerId string) (string, bool) {
        gameName = gameName+playerId
        playerDataStr, err := gm.rc.GetVal(gameName)
        if err != nil && err.Error() == REDIS_NIL {
            go log.Printf("\nERROR:GetPlayerData: Game %s, playerId %s not found, err:%v", gameName, playerId, err)
            return "player not found", false
        } else {
            return playerDataStr, true
        }
    }

    func (gm * GameManager) DelPlayerData(gameName string, playerId string) (int64, bool) {
        gm.DelPlayerName(gameName, playerId)
        gameName = gameName+playerId
        redisRet, err := gm.rc.DelKey(gameName)
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("\nERROR:DelPlayerData: Game %s, playerId %s not found, err:%v", gameName, playerId, err)
            return -1, false
        } else {
            return redisRet, true
        }
    }

    // store player data
    func (gm * GameManager) StorePlayerData(gameName string, playerData dt.PlayerData) (bool){
        gm.StorePlayerName(gameName, playerData.N, playerData.I)
        gameName = gameName+playerData.I
        err := gm.rc.SaveKeyValForever(gameName, dt.Str(playerData))
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("\nERROR:StorePlayerData: Game %s, playerData %v, err:%v", gameName, playerData, err)
            return false
        } else {
            go log.Printf("\nInfo: Success StorePlayerData: Game %s, playerData %v", gameName, playerData)
            return true
        }
    }

    // store player new score
    func (gm * GameManager) StorePlayerScore(gameName string,  score float64, playerId string) (bool){
        currHiScore, err := gm.GetPlayerHighScore(gameName, playerId)
        
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("ERROR:StorePlayerScore: Game %s, playerId %s not found. err:'%s'", gameName, playerId, err.Error() )
            return false
        } else {
            hiScoretoday, _ := gm.GetPlayerScoreOnDay(gameName,  playerId , 0) 
            if hiScoretoday < score {
                gm.StorePlayerScoreDaily(gameName , score , playerId)
            }
            if currHiScore < score {
                pDataStr, found := gm.GetPlayerData(gameName, playerId)
                if !found {
                    return false
                }
                pData := dt.JsonFromStr(pDataStr)
                pData.A = score 
                // a go routine to update 
                gm.StorePlayerData(gameName, pData)
                redisRet, redisErr := gm.rc.AddToSet(gameName, score, playerId)
                if redisErr != nil && redisErr.Error() != REDIS_NIL {
                    go log.Printf("Error:AddToSet: SUCESS gameName:%s, score:%f, playerId:%s, redisErr:%v", gameName, score, playerId, redisErr)
                    return false
                }   
                go log.Printf("Info:StorePlayerScore: SUCESS currHiScore:%.6f, newScore:%.6f, Game %s, playerId %s, retcode:%d", currHiScore, score, gameName, playerId, redisRet)
            } else {
                go log.Printf("Info:StorePlayerScore: Already high currHiScore:%.6f, newScore:%.6f, Game %s, playerId %s", currHiScore, score, gameName, playerId)
            }
            return true
        }
    }

    func getKeyForName(gameName string, playerId string)  string {
        return gameName+playerId+"Name"
    }

    // store player new score
    func (gm * GameManager) StorePlayerName(gameName string,  playerName string, playerId string) (bool){
        key := getKeyForName(gameName, playerId)
        err := gm.rc.SaveKeyValForever(key, playerName)
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("\nERROR:StorePlayerName: Game %s, playerName %s, err:%v", gameName, playerName, err)
            return false
        } else {
            go log.Printf("\nInfo: Success StorePlayerName: Game %s, playerName %s", gameName, playerName)
            return true
        }
    }

    // store player new score
    func (gm * GameManager) GetPlayerName(gameName string, playerId string) (string, bool){
        key := getKeyForName(gameName, playerId)
        playerName, err := gm.rc.GetVal(key)
        if err != nil && err.Error() == REDIS_NIL {
            go log.Printf("\nERROR:GetPlayerName: Game %s, playerId %s not found, err:%v", gameName, playerId, err)
            return "playerName not found", false
        } else {
            return playerName, true
        }
    }

    // store player new score
    func (gm * GameManager) DelPlayerName(gameName string,   playerId string) (int64, bool){
        key := getKeyForName(gameName, playerId)
        redisRet, err := gm.rc.DelKey(key)
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("\nERROR:DelPlayerName: Game %s, playerId %s not found, err:%v", gameName, playerId, err)
            return -1, false
        } else {
            return redisRet, true
        }
    }

    // delete player score
    func (gm * GameManager) DeletePlayerScore(gameName string,  playerId string) (bool){
        redisRet, redisErr := gm.rc.RemScore(gameName, playerId)
        if redisErr != nil && redisErr.Error() != REDIS_NIL {
            go log.Printf("Error:DeletePlayerScore: SUCESS gameName:%s, playerId:%s, redisErr:%v", gameName, playerId, redisErr)
            return false
        } else {
            go log.Printf("Info :DeletePlayerScore: SUCESS gameName:%s,  playerId:%s, redisRet:%d", gameName, playerId, redisRet)
        }
        return true
    }

    // get player rank
    func (gm * GameManager) GetPlayerRank(gameName string, playerId string) (int64) {
        rank, err := gm.rc.GetRank(gameName, playerId)
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("Error:GetPlayerRank: Game %s, playerId %s", gameName, playerId)
            return -1;
        } else {
            return rank+1;
        }
    }

    // get top x
    func (gm * GameManager) GetTopPlayers(gameName string, topCount int64) (string) {
        playeScores := make([]dt.PlayerScore, 0)

        topResults, err := gm.rc.GetTop(gameName, topCount)
        if err != nil && err.Error() != REDIS_NIL{
            go log.Printf("Error:GetTopPlayers: Game %s", gameName)
            return "json error"
        }
        topResultsVal := reflect.ValueOf(topResults)
        resultCount := topResultsVal.Len()
        for i:=0; i<resultCount; i++ {
            _score,_  := topResultsVal.Index(i).Field(0).Interface().(float64)
            _pid,_  := topResultsVal.Index(i).Field(1).Interface().(string)
            _name,_ := gm.GetPlayerName(gameName, _pid)
            playeScores = append(playeScores, dt.PlayerScore{_name, _score})
        }

        sort.Sort(dt.ByScoreRev(playeScores))
     
        if topCount < int64(len(playeScores)) {
            playeScores = playeScores[:topCount]
        }
        go log.Printf("Info: GetTopPlayers: top %d playeScores: %v", topCount, playeScores)
        b, jerr := json.Marshal(playeScores)
        if jerr == nil {
            return string(b)
        } else {
            return "json error"
        }
    }

    // get score
    func (gm * GameManager) GetPlayerHighScore(gameName string, playerId string) (float64, error) {
        return gm.rc.GetScore(gameName, playerId)
    }

    // store player new score for a week
    func (gm * GameManager) StorePlayerScoreOnADay(gameName string, score float64, playerId string, numOfDaysOld int) {
        gm.rc.AddToSet(gameName+util.GetDate(numOfDaysOld), score, playerId)
    }

    func (gm * GameManager) DeletePlayerScoreOnADay(gameName string,  playerId string, numOfDaysOld int) (bool){
        gameName = gameName+util.GetDate(numOfDaysOld)
        redisRet, redisErr := gm.rc.RemScore(gameName, playerId)
        if redisErr != nil && redisErr.Error() != REDIS_NIL {
            go log.Printf("Error:DeletePlayerScoreOnADay: SUCESS gameName:%s, playerId:%s, redisErr:%v", gameName, playerId, redisErr)
            return false
        } else {
            go log.Printf("Info :DeletePlayerScoreOnADay: SUCESS gameName:%s,  playerId:%s, redisRet:%d", gameName, playerId, redisRet)
        }
        return true
    }

    // store player new score for a week
    func (gm * GameManager) StorePlayerScoreDaily(gameName string, score float64, playerId string) {
        gm.rc.AddToSet(gameName+util.CurrentDate(), score, playerId)
    }

    // store player new score for a week
    func (gm * GameManager) GetPlayerScoreOnDay(gameName string, playerId string, numOfDaysOld int) (float64, error) {
        return gm.GetPlayerHighScore(gameName+util.GetDate(numOfDaysOld), playerId)
    }

    // get top weekly 1000
    func (gm * GameManager) GetTopPlayersOnDay(gameName string, topCount int64, numOfDaysOld int) (string) {
        if numOfDaysOld > 6 {
          return "";
        }

        playeScores := make([]dt.PlayerScore, 0)

        dateGameName := gameName+util.GetDate(numOfDaysOld)

        topResults, err := gm.rc.GetTop(dateGameName, topCount)
        if err != nil && err.Error() != REDIS_NIL{
            go log.Printf("Error:GetTopPlayersOnDay: dateGameName %s", dateGameName)
            return "json error"
        }
        topResultsVal := reflect.ValueOf(topResults)
        resultCount := topResultsVal.Len()
        for i:=0; i<resultCount; i++ {
            _score,_  := topResultsVal.Index(i).Field(0).Interface().(float64)
            _pid,_  := topResultsVal.Index(i).Field(1).Interface().(string)
            _name,_ := gm.GetPlayerName(gameName, _pid)
            playeScores = append(playeScores, dt.PlayerScore{_name, _score})
        }

        sort.Sort(dt.ByScoreRev(playeScores))
     
        if topCount < int64(len(playeScores)) {
            playeScores = playeScores[:topCount]
        }
        go log.Printf("Info: GetTopPlayersOnDay: top %d playeScores: %v", topCount, playeScores)
        b, jerr := json.Marshal(playeScores)
        if jerr == nil {
            return string(b)
        } else {
            return "json error"
        }

    }

    func (gm * GameManager) GetTopPlayersThisWeek(gameName string, topCount int64) (string) {
        playeScores := make([]dt.PlayerScore, 0)
        donePersons := make(map[string] bool) 

        for i:=6; i>=0; i--{
            topResults, err := gm.rc.GetTop(gameName+util.GetDate(i), topCount)
            if err != nil && err.Error() != REDIS_NIL{
                go log.Printf("Error:GetTopPlayersThisWeek: Game %s", gameName)
                continue
            }
            topResultsVal := reflect.ValueOf(topResults)
            resultCount := topResultsVal.Len()
            for i:=0; i<resultCount; i++ {
                _score,_  := topResultsVal.Index(i).Field(0).Interface().(float64)
                _pid,_  := topResultsVal.Index(i).Field(1).Interface().(string)
                _name,_ := gm.GetPlayerName(gameName, _pid)
                playeScores = append(playeScores, dt.PlayerScore{_name, _score})
            }
        }

        sort.Sort(dt.ByScoreRev(playeScores))

        for i:=0; i<len(playeScores) && i<int(topCount); i++ {
            if _,ok := donePersons[playeScores[i].N]; !ok {
                donePersons[playeScores[i].N] = true
            } else {
                playeScores = append(playeScores[:i], playeScores[i+1:]...) // perfectly fine if i is the last element https://play.golang.org/p/hcUEguyiTC
                i--
            }
        }
     
        if topCount < int64(len(playeScores)) {
            playeScores = playeScores[:topCount]
        }
        go log.Printf("Info: GetTopPlayersThisWeek: top %d playeScores: %v", topCount, playeScores)
        b, jerr := json.Marshal(playeScores)
        if jerr == nil {
            return string(b)
        } else {
            return "json error"
        }
    }

    // get rank among friends
    func (gm * GameManager) GetScoreOfFriends(gameName string, playerId string, friendIds []string) (string) {
        var topPlayersWithScores dt.ResponseData
        playerScore, err := gm.GetPlayerHighScore(gameName, playerId)
        if err != nil && err.Error() != REDIS_NIL {
            go log.Printf("Error:GetScoreOfFriends: Error: %v", err)
            return ""
        }
        
        totalCount := len(friendIds) + 1
        topPlayersWithScores.PlayerIds = make([]string, totalCount)
        topPlayersWithScores.Scores = make([]float64, totalCount)
        for i:=1; i<totalCount; i++ {
            topPlayersWithScores.PlayerIds[i] = friendIds[i-1]
            topPlayersWithScores.Scores[i] = -1
            score, err1 := gm.GetPlayerHighScore(gameName, friendIds[i-1])
            if err1 != nil && err1.Error() != REDIS_NIL {
                go log.Printf("Error:GetScoreOfFriends: Game %s, %v", gameName, err1)
            } else {
                topPlayersWithScores.Scores[i] = score
            }
        }
        
        topPlayersWithScores.PlayerIds[0] = playerId
        topPlayersWithScores.Scores[0] =playerScore
        b, jerr := json.Marshal(topPlayersWithScores)
        if jerr == nil {
            return string(b)
        } else {
            return "json error"
        }
    }


Here is the test code:

    package gamedatamanager_test

    import (
        dt   "gogameserver/datatypes"
        gdm  "gogameserver/gamedatamanager"
        util "gogameserver/util"

        "testing"
        "math/rand"
        "time"
        "strconv"
        "encoding/json"

        "sort"
    )

    const GAMENAME string  = "00dummygame" 
    const PLAYERID string  = "00playerid"
    var PLAYERIDS  = [] string{"00NeverAddThispid0", "00NeverAddThispid1",  "00NeverAddThispid3", "00NeverAddThispid4", "00NeverAddThispid5"}

    func TestStorePlayerData(t *testing.T) {
        gm := gdm.New()
        playerData := dt.NewWithId(PLAYERID) 
        done := gm.StorePlayerData(GAMENAME, playerData)
        if !done {
            t.Errorf("Data shall have been stored\n")
        } 
        gm.DelPlayerData(GAMENAME, PLAYERID)
    }

    func TestGetPlayerData(t *testing.T) {
        gm := gdm.New()
        playerData := dt.NewWithId(PLAYERID) 
        done := gm.StorePlayerData(GAMENAME, playerData)
        if !done {
            t.Errorf("Error: Data shall have been stored\n")
        } 
        playerDataStr := dt.Str(playerData)
        playerDataStrFromDB, found := gm.GetPlayerData(GAMENAME, PLAYERID)
        if !found {
            t.Errorf("Error: GetPlayerData: Data shall have been found\n")
        } else {
            if playerDataStrFromDB != playerDataStr {
                t.Errorf("Error: playerDataStr from redis: %s\n\tplayerDataStr shall have been %s\n", playerDataStrFromDB, playerDataStr)
            }
        }
        gm.DelPlayerData(GAMENAME, PLAYERID)
    }

    func TestStorePlayerScore(t *testing.T) {
        gm := gdm.New()
        playerData := dt.NewWithId(PLAYERID) 
        playerData.A = 10.0
        newScore := 10000.0
        gm.DeletePlayerScore(GAMENAME, PLAYERID)
        gm.StorePlayerData(GAMENAME, playerData)
        success := gm.StorePlayerScore(GAMENAME, newScore, PLAYERID)
        if !success {
            t.Errorf("Error: StorePlayerScore: Data shall have been found\n")
        } else {
            newHiScore, err := gm.GetPlayerHighScore(GAMENAME, PLAYERID)
            if err != nil {
                t.Errorf("TestStorePlayerScore Error: GetPlayerHighScore, Error: %v\n", err)
            } else {
                if newHiScore != newScore {
                    t.Errorf("TestStorePlayerScore Error: newHiScore=%d. Added newScore=%d\n", newHiScore, newScore)
                }
                playerDataStrFromDB, success := gm.GetPlayerData(GAMENAME, PLAYERID)
                if !success {
                    t.Errorf("TestStorePlayerScore Error: GetPlayerData\n")
                } else {
                    playerData.A = newScore
                    playerDataStr :=  dt.Str(playerData)
                    if playerDataStrFromDB != playerDataStr {
                        t.Errorf("TestStorePlayerScore Error: playerDataStr from redis: %s\n\tplayerDataStr shall have been %s\n", playerDataStrFromDB, playerDataStr)
                    }
                }
            }
        }
        gm.DelPlayerData(GAMENAME, PLAYERID)
        gm.DeletePlayerScore(GAMENAME, PLAYERID)
    }

    func TestGetPlayerRank(t *testing.T) {
        gm := gdm.New()
        scores := []float64{2,1,7,4, 3}
        for i:=0; i<5; i++ {
            gm.DeletePlayerScore(GAMENAME, PLAYERIDS[i])
            playerData := dt.NewWithId(PLAYERIDS[i]) 
            playerData.A = scores[i]
            gm.StorePlayerData(GAMENAME, playerData)
            gm.StorePlayerScore(GAMENAME, scores[i], PLAYERIDS[i])
        }
        rank := gm.GetPlayerRank(GAMENAME, PLAYERIDS[2])
        if rank != 1{
            t.Errorf("TestGetPlayerRank Error: Player rank should have been 1 but is : %d\n", rank)
        }
        for i:=0; i<5; i++ {
            gm.DelPlayerData(GAMENAME, PLAYERIDS[i])
            gm.DeletePlayerScore(GAMENAME, PLAYERIDS[i])
        }
    }


    func TestGetScoreOfFriends(t *testing.T) {
        gm := gdm.New()
        scores := []float64{2,1,7,4, 3}
        for i:=0; i<5; i++ {
            gm.DeletePlayerScore(GAMENAME, PLAYERIDS[i])
            playerData := dt.NewWithId(PLAYERIDS[i]) 
            playerData.A = scores[i]
            gm.StorePlayerData(GAMENAME, playerData)
            gm.StorePlayerScore(GAMENAME, scores[i], PLAYERIDS[i])
        }
        scoresOfFriends := gm.GetScoreOfFriends(GAMENAME, PLAYERIDS[0], PLAYERIDS[2:5])
        scoresOfFriendsExpectedStr := "{\"PlayerIds\":[\"00NeverAddThispid0\",\"00NeverAddThispid3\",\"00NeverAddThispid4\",\"00NeverAddThispid5\"],\"Scores\":[2,7,4,3]}"
        if scoresOfFriends != scoresOfFriendsExpectedStr{
            t.Errorf("TestGetScoreOfFriends Error: scoresOfFriends str is : %s\n", scoresOfFriends)
        }

        for i:=0; i<5; i++ {
            gm.DelPlayerData(GAMENAME, PLAYERIDS[i])
            gm.DeletePlayerScore(GAMENAME, PLAYERIDS[i])
        }
    }

    func TestGetTopPlayers(t *testing.T) {
        gm := gdm.New()
        scores := []float64{2,1,7,4, 3}
        names  := make([] string, 5)

        playeScores := make([]dt.PlayerScore, 0)
        gm.DelKey(GAMENAME)

        for i:=0; i<5; i++ {
            names[i] = util.RandStringRunes(5)
            gm.DeletePlayerScore(GAMENAME, PLAYERIDS[i])
            playerData := dt.NewWithId(PLAYERIDS[i]) 
            playerData.A = scores[i]
            playerData.N = names[i]
            gm.StorePlayerData(GAMENAME, playerData)
            gm.StorePlayerScore(GAMENAME, scores[i], PLAYERIDS[i])

            playeScores = append(playeScores, dt.PlayerScore{names[i], scores[i]})
        }

        sort.Sort(dt.ByScoreRev(playeScores))
        topCount := 3
        top3 := gm.GetTopPlayers(GAMENAME, int64(topCount) )
        
        var top3Scorers []dt.PlayerScore
        json.Unmarshal([]byte(top3), &top3Scorers)

        for i:=0; i<topCount; i++{
            if playeScores[i].N != top3Scorers[i].N || playeScores[i].S != top3Scorers[i].S {
                t.Errorf("Error: TestGetTopPlayers,  playeScores[i] : %v\n, top3Scorers[i]: %v\n", playeScores[i], top3Scorers[i])
            }
        }

        for i:=0; i<5; i++ {
            gm.DelPlayerData(GAMENAME, PLAYERIDS[i])
            gm.DeletePlayerScore(GAMENAME, PLAYERIDS[i])
        }

    } 

    func TestGetTopPlayersThisWeek(t *testing.T) {
        gm := gdm.New()

        r := rand.New(rand.NewSource(time.Now().UnixNano()))
       
        scores := make([] float64, 0)
        names  := make([] string, 10)
        id     := make([] string, 10)

        for i:=0; i<10; i++ {
            names[i] = util.RandStringRunes(5)
            id[i] = strconv.Itoa(i)
            playerData := dt.NewWithId(id[i]) 
            playerData.N = names[i]
            gm.StorePlayerData(GAMENAME, playerData)
        }


        playerMaxScore := make(map[string] float64)
        for i:=0; i<10; i++ {
            playerMaxScore[names[i]] = 0
        }

        // for 7 days
        for d:=0; d<7; d++ {
            gm.DelKey(GAMENAME+util.GetDate(d))
            for i:=0; i<10; i++ {
                score := r.Float64()*100
                scores = append(scores, score)
                if playerMaxScore[names[i]] < score {
                   playerMaxScore[names[i]] = score
                }
                gm.StorePlayerScoreOnADay(GAMENAME, score, id[i], d) 
            }
        } 

        playeScores := make([]dt.PlayerScore, 0)
        for k,v := range playerMaxScore {
            playeScores = append(playeScores, dt.PlayerScore{k, v})
        }
       
        sort.Sort(dt.ByScoreRev(playeScores))

        topCount := 5
        topWeeklyScorersJson := gm.GetTopPlayersThisWeek(GAMENAME, int64(topCount) )
        
        var topWeeklyScorers []dt.PlayerScore
        json.Unmarshal([]byte(topWeeklyScorersJson), &topWeeklyScorers)

        for i:=0; i<topCount; i++{
            if playeScores[i].N != topWeeklyScorers[i].N || playeScores[i].S != topWeeklyScorers[i].S {
                t.Errorf("Error: TestGetTopPlayersThisWeek,  playeScores[i] : %v\n, topWeeklyScorers[i]: %v\n", playeScores[i], topWeeklyScorers[i])
            }
        }

        for i:=0; i<10; i++ {
            gm.DelPlayerData(GAMENAME, id[i])
        }

        for d:=0; d<7; d++ {
            for i:=0; i<10; i++ {
                gm.DeletePlayerScoreOnADay(GAMENAME ,  id[i], d)
            }
        }
    }


Here is the complete GoGameServer: https://github.com/ediston/gogameserver

Please review it and tell me how can I write better code.

  [1]: https://codereview.stackexchange.com/questions/150207/redis-client-go-based-game-server