Home > Software engineering >  Is it possible to assign to a regular variable and slice in the same statement?
Is it possible to assign to a regular variable and slice in the same statement?

Time:09-24

I'm making a chess game and I want to do a series of type assertions in the same var statement, then pass them to a function that handles it, but apparently, Go doesn't allow me to assign to a regular variable and a slice index in the same statement:

// inside a function:
asserts := make([]bool, 0, 10)
assertionHandler := func(ok *[]bool) {
    for _, b := range *ok {
        if !b {
            msg := "pieceCliked: failed while trying to do type assertion\n%s\n\n"
            utils.LogPrintError(errors.New(fmt.Sprintf(msg, string(debug.Stack()))))
        }
    }
    *ok = make([]bool, 0, 10)
}

var (
    possibleSquares []string
    // The following results in a syntax error: expected type, found '='
    dataObject, asserts[0]  = data.(map[string]any) 
    playerData, asserts[1]  = dataObject["playerData"].(map[string]any)
    square, asserts[2]      = playerData["selectedPieceLocation"].(string)
    piece, asserts[3]       = playerData["selectedPiece"].(string)
    color, asserts[4]       = playerData["selectedPieceColor"].(string)
)
assertionHandler(asserts)

Is it possible to do what I'm trying to do?

CodePudding user response:

Not the way you're doing it, no. A var block defines new variables and their types, but you're trying to assign to both new variables with no types (hence the error expected type) and elements of an existing slice within that block.

You could do:

var (
    possibleSquares []string
    dataObject map[string]any
    playerData map[string]any
    square string
    piece string
    color string
)

dataObject, asserts[0]  = data.(map[string]any) 
playerData, asserts[1]  = dataObject["playerData"].(map[string]any)
square, asserts[2]      = playerData["selectedPieceLocation"].(string)
piece, asserts[3]       = playerData["selectedPiece"].(string)
color, asserts[4]       = playerData["selectedPieceColor"].(string)

CodePudding user response:

Another answer describes why the code in the question does not work. Here's another workaround:

Write assertion handler to use variadic argument:

func assertionHandler(asserts ...bool) bool {
    result := true
    for _, b := range assserts {
        if !b {
            result = false
            msg := "pieceCliked: failed while trying to do type assertion\n%s\n\n"
            utils.LogPrintError(errors.New(fmt.Sprintf(msg, string(debug.Stack()))))
        }
    }   
    return result
}

Use short variable declarations to collect the values and bool results:

dataObject, assert0 := data.(map[string]any) 
playerData, assert1 := dataObject["playerData"].(map[string]any)
square, assert2     := playerData["selectedPieceLocation"].(string)
piece, assert3      := playerData["selectedPiece"].(string)
color, assert4      := playerData["selectedPieceColor"].(string)
if !assertionHandler(assert0, assert1, assert2, assert3, assert4) {
   return
}
  • Related