Im currently learning GO and i decided to redo a character ranker i made in python a year ago as an exercise. The program takes user input and makes a slice of structs with them (the struct consists of a name inputted and a score of 0), then a function creates matches between the inputed characters so the user can choose between the two in pair. full code here
type Char struct {
Name string
Score uint8
}
func main() {
baseSlice := InputCharacters()
matchups := MatchMaking(baseSlice)
voting := Voting(matchups)
n := 0
for _, v := range voting {
fmt.Printf("%d: %v(%v)\n", n, v.Name, v.Score)
n++
}
/* the for returns 2 copies of each character,
none of them have any points */
}
func InputCharacters() []structs.Char {
var charSlice []structs.Char = []structs.Char{}
var reader = bufio.NewReader(os.Stdin)
for {
fmt.Println("Enter a character name (or quit/q to finish):")
name, err := reader.ReadString('\n')
name = strings.TrimSpace(name)
if err != nil {
fmt.Printf("Reading error: %v", err)
}
if name == "quit" || name == "q" {
return charSlice
}
for i := range charSlice {
if charSlice[i].Name == name {
charSlicePostDelete := structs.RemoveElement(charSlice, i)
charSlice = charSlicePostDelete
break
}
}
charSlice = append(charSlice, structs.Char{Name: name, Score: 0})
}
}
func MatchMaking(arr []structs.Char) map[[2]structs.Char]bool {
m := make(map[[2]structs.Char]bool)
for _, v1 := range arr {
for _, v2 := range arr {
pair := [2]structs.Char{v1, v2}
if pair[0].Name == pair[1].Name {
continue
}
sortedPair := [2]structs.Char{SortAlphabetically(pair[0], pair[1]), SortAlphabeticallyReverse(pair[0], pair[1])}
if _, ok := m[sortedPair]; !ok {
m[sortedPair] = true
}
}
}
return m
}
func Voting(pairs map[[2]structs.Char]bool) []structs.Char {
var reader = bufio.NewReader(os.Stdin)
for i := range pairs {
fmt.Println("Vote for your favourite (0 for left, 1 for right)")
fmt.Printf("%v - %v\n", i[0].Name, i[1].Name)
name, err := reader.ReadString('\n')
name = strings.TrimSpace(name)
if err != nil {
fmt.Printf("Reading error: %v", err)
}
nameToInt, err := strconv.ParseInt(name, 0, 8)
if err != nil {
fmt.Printf("Reading error: %v", err)
}
switch nameToInt {
case 0:
i[0].Score = i[0].Score + 1
case 1:
i[1].Score = i[1].Score + 1
}
}
var charArr []structs.Char = make([]structs.Char, 0, len(pairs)*2)
for i := range pairs {
charArr = append(charArr, i[0], i[1])
}
return charArr
}
func SortAlphabetically(a, b structs.Char) structs.Char {
if a.Name < b.Name {
return a
}
return b
}
func SortAlphabeticallyReverse(a, b structs.Char) structs.Char {
if a.Name > b.Name {
return a
}
return b
}
I want the Matchmaking func to return pointers to the elements of the original []structs.Char instead of copies, so that i can then change the score property in a different function and that change will be seen in the original slice. The MatchMaking() func instead returns a different copy of the char struct each type that struct instance is needed, so if Mathmaking returns two pairs with the struct 'c', each 'c' will be a different copy of that struct. I'm a bit confused by the concept of pointers and how they work in go so im not sure how to implement this to my functions.
The wording is a bit fuzzy(you use 'return' a lot in contexts where I think you mean use or pass), but what I believe that you want is to change the underlying values in the Char structs. For that, we'll use pointers to Char
- *Char
(in this case, a map of pairs of *Char
to bool
) in both the MatchMaking
and the Voting
methods. That way any change you do propagates to the base structs, since you're now passing pointers around instead of struct copies
func MatchMaking(arr []Char) map[[2]*Char]bool {
m := make(map[[2]*Char]bool)
for i := 0; i < len(arr); i++ {
for j := i + 1; j < len(arr); j++ {
pair := [2]*Char{&arr[i], &arr[j]}
if pair[0].Name == pair[1].Name {
continue
}
sortedPair := [2]*Char{SortAlphabetically(pair[0], pair[1]), SortAlphabeticallyReverse(pair[0], pair[1])}
if _, ok := m[sortedPair]; !ok {
m[sortedPair] = true
}
}
}
return m
}
func Voting(pairs map[[2]*Char]bool) []Char {
var reader = bufio.NewReader(os.Stdin)
for i := range pairs {
fmt.Println("Vote for your favourite (0 for left, 1 for right)")
fmt.Printf("%v - %v\n", (*i[0]).Name, (*i[1]).Name)
name, err := reader.ReadString('\n')
name = strings.TrimSpace(name)
if err != nil {
fmt.Printf("Reading error: %v", err)
}
nameToInt, err := strconv.ParseInt(name, 0, 8)
if err != nil {
fmt.Printf("Reading error: %v", err)
}
switch nameToInt {
case 0:
(*i[0]).Score++
case 1:
(*i[1]).Score++
}
}
var charArr []Char = make([]Char, 0, len(pairs)*2)
for i := range pairs {
charArr = append(charArr, *i[0], *i[1])
}
return charArr
}