在同一语句中给一个普通变量赋值并进行切片操作,这种操作是可能的吗?

huangapple go评论86阅读模式
英文:

Is it possible to assign to a regular variable and slice in the same statement?

问题

我正在制作一个国际象棋游戏,我想在同一个var语句中进行一系列的类型断言,然后将它们传递给一个处理函数,但显然,Go语言不允许我在同一个语句中给普通变量和切片索引赋值:

// 在一个函数内部:
asserts := make([]bool, 0, 10)
assertionHandler := func(ok *[]bool) {
	for _, b := range *ok {
		if !b {
			msg := "pieceCliked: 在尝试进行类型断言时失败\n%s\n\n"
			utils.LogPrintError(errors.New(fmt.Sprintf(msg, string(debug.Stack()))))
		}
	}
	*ok = make([]bool, 0, 10)
}

var (
	possibleSquares []string
	// 下面的代码会导致语法错误:期望类型,但找到了'='
	dataObject, asserts[0]  = data.(map[string]interface{}) 
	playerData, asserts[1]  = dataObject["playerData"].(map[string]interface{})
	square, asserts[2]      = playerData["selectedPieceLocation"].(string)
	piece, asserts[3]       = playerData["selectedPiece"].(string)
	color, asserts[4]       = playerData["selectedPieceColor"].(string)
)
assertionHandler(asserts)

我尝试做的事情是可行的吗?

英文:

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?

答案1

得分: 2

你这样做是不对的。var 块用于定义新的变量及其类型,但你试图在没有类型的情况下给新变量和现有切片中的元素赋值,所以出现了错误 expected type

你可以这样做:

var (
    possibleSquares []string
    dataObject map[string]interface{}
    playerData map[string]interface{}
    square string
    piece string
    color string
)

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

注意,我将 any 类型更改为了 interface{} 类型,因为 Go 语言中没有 any 类型。

英文:

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)

答案2

得分: 1

另一个答案描述了为什么问题中的代码不起作用。这里是另一种解决方法:

编写断言处理程序来使用可变参数:

func assertionHandler(asserts ...bool) bool {
    result := true
    for _, b := range asserts {
        if !b {
            result = false
            msg := "pieceCliked: 在尝试进行类型断言时失败\n%s\n\n"
            utils.LogPrintError(errors.New(fmt.Sprintf(msg, string(debug.Stack()))))
        }
    }   
    return result
}

使用短变量声明来收集值和布尔结果:

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

请注意,我已经将 any 类型更改为 interface{} 类型,因为 Go 语言中没有 any 类型。

英文:

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
}

huangapple
  • 本文由 发表于 2022年9月24日 00:03:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/73830368.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定