Понимание составного литерала go
Почему присвоение значения функции f не является составным литералом?
Спецификация Go lang Составные литералы говорят ниже, следовательно, значение функции не может быть построено с помощью составного литерала.
Составные литералы создают значения для структур, массивов, срезов и карт и создают новое значение каждый раз, когда они оцениваются.
Однако присвоение значения функции функции f в коде выглядит как составное литеральное выражение для типа func () int.
Есть ли причина, по которой объект функции не может быть построен как составной литерал?
package main
import (
"fmt"
)
func main(){
var x int = 0
var f func() int
f = func() int{ x++; return x * x } // <---- Why this cannot be a composite literal?
fmt.Println(f()) // 1
fmt.Println(f()) // 4
fmt.Println(f()) // 9
// Define a type for "func() int" type
type SQUARE func() int
g := SQUARE{ x++; return x * x} // <--- Error with Invalid composite literal type: SQUARE
fmt.Println(g())
}
2 ответа
Делает f = func() int{ x++; return x * x }
выглядит как составной литерал?
На самом деле, нет)
Составные литералы создают значения для структур, массивов, срезов и карт... Они состоят из типа литерала, за которым следует список элементов, связанный фигурными скобками.
Чтобы сделать это утверждение более ясным, вот производственное правило для составного литерала:
CompositeLit = LiteralType LiteralValue .
Вы можете видеть, что производственное правило для LiteralValue
является:
LiteralValue = "{" [ ElementList [ "," ] ] "}" .
а также FunctionBody
, совсем не выглядит так. По сути, это списокStatement
s:
FunctionBody = Block .
Block = "{" StatementList "}" .
StatementList = { Statement ";" } .
Почему функция не может быть построена как составной литерал?
Я не смог найти какой-либо задокументированный ответ на этот вопрос, но самое простое предположение состоит в том, что основные причины:
- Избежать путаницы. Вот пример, если бы можно было создать составной литерал для функции:
type SquareFunc func() int
type Square struct {
Function SquareFunc
}
func main() {
f := SquareFunc{ return 1 }
s := Square{ buildSquareFunc() }
}
s:= ...
строка (которая должна быть составного типа) может быть легко перепутана с первой строкой.
- Помимо тела, у функции есть еще одна важная вещь -
Signature
. Если бы вы могли построить составной литерал для функции, как бы вы определяли его аргументы и возвращали имена параметров? Вы можете определить имена в определении типа, но это вызовет негибкость (иногда вы хотите использовать другие имена параметров) и код вроде:
type SquareFunc func(int x) int
func main() {
x := 1
f := SquareFunc{
x++
return x * x
}
f(2)
}
выглядело бы слишком неясно, так как не было бы очевидно, что x
переменная действительно использует.
Вам нужно его отформатировать.
package main
import (
"fmt"
)
func main(){
var x int = 0
var f func() int
f = (func() int{ x++; return x * x }) // <---- Why this cannot be a composite literal?
fmt.Println(f()) // 1
fmt.Println(f()) // 4
fmt.Println(f()) // 9
// Define a type for "func() int" type
type SQUARE func() int
g := SQUARE(func()int{ x++; return x * x}) // <--- Error with Invalid composite literal type: SQUARE
fmt.Println(g())
}
Оберните вашу переменную f
с помощью ()
. В случаеSQUARE
, вам нужно написать func() int
перед запуском кода вашей функции