A couple months back I made a go fish game in Go, just for the sake of that pun. It was pretty poorly done and made experienced Go-ers cry when they looked at it. I rewrote some of it to be more standard, but I'd still like critiques from the 95% of the world with more Go experience than me.For those unaware, Go Fish is a children's game where each player has a hand of cards and takes turns calling out a card value, if anyone else has that card they have to give it to them, your turn ends when noone has a card that you call out, and you have to draw a card from the deck before the next person takes their turn. The game ends when there are no more cards in the deck and the winner is whoever gets the most four-of-a-kinds during the game.package mainimport (    fmt    math/rand    sort    time)var cards = [13]string{2, 3, 4, 5, 6, 7, 8, 9,    10, J, Q, K, A}//GoFishGame Stores the game state.type GoFishGame struct {    hands  [][]string    deck   []string    turn   int    scores []int}// checkForBooks looks for fours of a kind// and scores them if we have them.// If we run out of cards, we draw more.func (gm *GoFishGame) checkForBooks() {    sort.Strings(gm.hands[gm.turn])    prev :=     count := 1    for _, card := range gm.hands[gm.turn] {        if card == prev {            count++            if count == 4 {                fmt.Printf(Book of %s.\n, card)                gm.stealCards(card, gm.turn)                gm.scores[gm.turn]++                if gm.isHandEmpty() {                    gm.drawCard()                }            }        } else {            count = 1        }        prev = card    }}// drawCard takes a card from the deck// adding it to the current player's hand.func (gm *GoFishGame) drawCard() {    if !gm.isDeckEmpty() {        card := gm.deck[0]        gm.deck = gm.deck[1:]        if gm.turn == 0 {            fmt.Printf(You drew a %s.\n, card)        }        gm.hands[gm.turn] = append(gm.hands[gm.turn], card)        //Check for books        gm.checkForBooks()    }}// endPly ends the current person's turn.// It then either calls the next person's// turn or prints a game over message.func (gm *GoFishGame) endPly() {    gameOver := gm.isGameOver()    if gameOver {        gm.printGameOverMessage()    } else if gm.turn == 1 {        gm.playerTurn(getPickComputer)    } else {        gm.playerTurn(getPickUser)    }}// getPickComputer handles the computer's card choices.// We do the moderately smart thing of pick a random// card from our handfunc getPickComputer(gm *GoFishGame) string {    hand := gm.hands[1]    choice := A    if len(hand) > 0 {        choice = hand[rand.Intn(len(hand))]    }    fmt.Printf(Computer picks %s.\n, choice)    return choice}// getPickUser gets the user's move.// If it's not valid, then the user just wastes// their turn.func getPickUser(gm *GoFishGame) string {    fmt.Println(What card do you want?)    var card string    fmt.Scanf(%s\n, &card)    return card}// isDeckEmpty returns if the deck is empty.func (gm *GoFishGame) isDeckEmpty() bool {    return len(gm.deck) == 0}// isHandEmpty returns if the current player's hand is empty.func (gm *GoFishGame) isHandEmpty() bool {    return len(gm.hands[gm.turn]) == 0}// isGameOver returns if the game is over.// This happens when all 13 pips have been made into sets.func (gm *GoFishGame) isGameOver() bool {    return gm.scores[0]+gm.scores[1] == 13}// makeDeck makes a deck.// The deck is 52 cards with 4 of each pip.func makeDeck() []string {    rand.Seed(time.Now().UTC().UnixNano())    deck := make([]string, 52)    perm := rand.Perm(52)    for indx := range perm {        tVal := perm[indx]        card := cards[tVal/4]        deck[indx] = card    }    return deck}// opponentHas returns if the opponent's hand has a card.func (gm *GoFishGame) opponentHas(find string) bool {    for _, card := range gm.hands[(gm.turn+1)%2] {        if card == find {            return true        }    }    return false}// playerTurn handles the major game logic.// It's used for both the player's and computer's turns,// with the different behavior handled by the getPick param.func (gm *GoFishGame) playerTurn(getPick func(*GoFishGame) string) {    opponent := (gm.turn + 1) % 2    gm.checkForBooks()    if opponent == 1 {        gm.printHand()    }    if gm.isHandEmpty() {        gm.drawCard()    }    gameOver := gm.isGameOver()    if !gameOver {        card := getPick(gm)        if gm.opponentHas(card) {            count := gm.stealCards(card, opponent)            for indx := 0; indx < count; indx++ {                gm.hands[gm.turn] = append(gm.hands[gm.turn], card)            }            gm.checkForBooks()        } else {            fmt.Println(GO FISH!)            gm.drawCard()            gm.turn = opponent        }    }    gm.endPly()}// printGameOverMessage prints the appropriate end message.func (gm *GoFishGame) printGameOverMessage() {    fmt.Printf(Final score is %d to %d.\n, gm.scores[0], gm.scores[1])    if gm.scores[0] > gm.scores[1] {        fmt.Println(Player wins!)    } else if gm.scores[0] == gm.scores[1] {        fmt.Println(It's a tie.)    } else {        fmt.Println(Computer wins!)    }}// printHand print's the player's hand and current score.func (gm *GoFishGame) printHand() {    sort.Strings(gm.hands[0])    fmt.Printf(You have: %s.\n, gm.hands[0])    fmt.Printf(Score is %d to %d.\n, gm.scores[0], gm.scores[1])}// stealCards removes all instances of a card from side's hand.func (gm *GoFishGame) stealCards(purge string, side int) int {    count := 0    tList := gm.hands[side]    var filtered []string    for _, card := range tList {        if purge == card {            count++        } else {            filtered = append(filtered, card)        }    }    gm.hands[side] = filtered    return count}// main creates the deck and initial hands.func main() {    deck := makeDeck()    playerHand := deck[0:9]    compHand := deck[9:18]    deck = deck[18:]    hands := make([][]string, 2, 2)    hands[0] = playerHand    hands[1] = compHand    scores := make([]int, 2, 2)    scores[0] = 0    scores[1] = 0    game := GoFishGame{hands, deck, 0, scores}    game.playerTurn(getPickUser)}I have three things that I think might be issues. First, I use 0/1 both as flags saying whose turn it is and then use them as array indexes for GoFishGame.hands and GoFishGame.score. Second, this program seems to be done assuming tail call optimization, that's not a thing in Go, but since the stack depth is reasonably bounded it doesn't seem like an issue to me. Third, I'm not sure how to name methods and structs.
Go Fish game written in Go
beginner;playing cards;go