基础面值
面值是在程序代码中直接表示的值,其它的非零初始值只能由面值常量或常量表达式生成。比如表达式x+2*y的2就是面值,而x和y则不是面值而是标识符。Go语言规范明确定义了基础面值只有整数、浮点数、复数、符文和字符串几种类型。
type BasicLit struct {ValuePos token.Pos // literal positionKind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRINGValue string // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`}func main() {expr, _ := parser.ParseExpr(`"9527"`)ast.Print(nil, expr)}-------------------------------output-------------------------------0 *ast.BasicLit {1 . ValuePos: 12 . Kind: STRING3 . Value: "\"9527\""4 }
标识符面值
type Ident struct {NamePos token.Pos // identifier positionName string // identifier nameObj *Object // denoted object; or nil}func main() {expr, _ := parser.ParseExpr(`x`)ast.Print(nil, expr)}-------------------------------output-------------------------------0 *ast.Ident {1 . NamePos: 12 . Name: "x"3 . Obj: *ast.Object {4 . . Kind: bad5 . . Name: ""6 . }7 }
ast.Object是一个相对复杂的结构,其中Kind用于描述标识符的类型:
const (Bad ObjKind = iota // for error handlingPkg // packageCon // constantTyp // typeVar // variableFun // function or methodLbl // label)
Bad表示未知的类型,其它的分别对应Go语言中包、常量、类型、变量、函数和标号等语法结构。
复合面值
在基础面值,我们已经见过整数、浮点数、复数、符文和字符串等一些简单的面值。除了基础面值之外,还有结构体面值、map面值和函数面值等。本节讨论复合面值的语法树表示。
函数面值
func main() {expr, _ := parser.ParseExpr(`func(){}`)ast.Print(nil, expr)}---------------------------output-------------------------0 *ast.FuncLit {1 . Type: *ast.FuncType {2 . . Func: 13 . . Params: *ast.FieldList {4 . . . Opening: 55 . . . Closing: 66 . . }7 . }8 . Body: *ast.BlockStmt {9 . . Lbrace: 710 . . Rbrace: 811 . }12 }
函数面值的语法树由ast.FuncLit结构体表示,其中再由Type成员表示类型,Body成员表示函数体语句。
我们可以对比下ast.FuncLit和ast.FuncDecl结构体的差异:
type FuncLit struct {Type *FuncType // function typeBody *BlockStmt // function body}type FuncDecl struct {Doc *CommentGroup // associated documentation; or nilRecv *FieldList // receiver (methods); or nil (functions)Name *Ident // function/method nameType *FuncType // function signature: parameters, results, and position of "func" keywordBody *BlockStmt // function body; or nil for external (non-Go) function}
复合类型面值语法
复合型面值的语法树通过ast.CompositeLit表示:
type CompositeLit struct {Type Expr // literal type; or nilLbrace token.Pos // position of "{"Elts []Expr // list of composite elements; or nilRbrace token.Pos // position of "}"Incomplete bool // true if (source) expressions are missing in the Elts list}
其中ast.CompositeLit.Type对应复合类型的表达式,然后ast.CompositeLit.Elts是复合类型初始元素列表。初始元素列表可以是普通的值,也可能是Key-Value下标和值对,而且初始值还可能是其它的复合面值。
数组和切片面值
func main() {expr, _ := parser.ParseExpr(`[...]int{1,2:3}`)ast.Print(nil, expr)}---------------------------output-------------------------0 *ast.CompositeLit {1 . Type: *ast.ArrayType {2 . . Lbrack: 13 . . Len: *ast.Ellipsis {4 . . . Ellipsis: 25 . . }6 . . Elt: *ast.Ident {7 . . . NamePos: 68 . . . Name: "int"9 . . . Obj: *ast.Object {10 . . . . Kind: bad11 . . . . Name: ""12 . . . }13 . . }14 . }15 . Lbrace: 916 . Elts: []ast.Expr (len = 2) {17 . . 0: *ast.BasicLit {18 . . . ValuePos: 1019 . . . Kind: INT20 . . . Value: "1"21 . . }22 . . 1: *ast.KeyValueExpr {23 . . . Key: *ast.BasicLit {24 . . . . ValuePos: 1225 . . . . Kind: INT26 . . . . Value: "2"27 . . . }28 . . . Colon: 1329 . . . Value: *ast.BasicLit {30 . . . . ValuePos: 1431 . . . . Kind: INT32 . . . . Value: "3"33 . . . }34 . . }35 . }36 . Rbrace: 1537 . Incomplete: false38 }
复合面值语法树由ast.CompositeLit结构体表示,其中ast.CompositeLit.Type成员为ast.ArrayType表示这是数组或切片类型(如果没有长度信息则为切片类型,否则就是数组),而ast.CompositeLitElts成员则是元素的值。初始元素是一个[]ast.Expr类型的切片,每个元素依然是一个表达式。数组的第一个元素是ast.BasicLit类型,表示这是一个基础面值类型。数组的第二个元素是ast.KeyValueExpr方式指定的,其中Key对应的数组下标是2,Value对应的值为3。
数组和切片语法的最大差别是数组有长度信息。在这个例子中数组是通过…省略号表达式自动计算数组的长度,在语法树中对应的是ast.Ellipsis表达式类型。如果ast.ArrayType结构体中的Len成员是空指针,则表示这是一个切片类型,否则对应可以生成数组长度的表达式。
结构体面值
func main() {expr, _ := parser.ParseExpr(`struct{X int}{X:1}`)ast.Print(nil, expr)}---------------------------output-------------------------0 *ast.CompositeLit {1 . Type: *ast.StructType {...}32 . Lbrace: 1433 . Elts: []ast.Expr (len = 1) {34 . . 0: *ast.KeyValueExpr {35 . . . Key: *ast.Ident {36 . . . . NamePos: 1537 . . . . Name: "X"38 . . . }39 . . . Colon: 1640 . . . Value: *ast.BasicLit {41 . . . . ValuePos: 1742 . . . . Kind: INT43 . . . . Value: "1"44 . . . }45 . . }46 . }47 . Rbrace: 1848 . Incomplete: false49 }
结构体面值依然是通过ast.CompositeLit结构体描述。结构体中成员的初始化通过ast.KeyValueExpr结构体初始化,Key部分为X表示成员名字,Value部分为X成员的初始值。
当然,结构体的初始化也可以不声明成员的名字:
func main() {expr, _ := parser.ParseExpr(`struct{X int}{1}`)ast.Print(nil, expr)}---------------------------output-------------------------33 . Elts: []ast.Expr (len = 1) {34 . . 0: *ast.BasicLit {35 . . . ValuePos: 1536 . . . Kind: INT37 . . . Value: "1"38 . . }39 . }
只有一个元素是通过ast.BasicLit对应的基础面值表示,对应结构体的第一个成员。
map面值
func main() {expr, _ := parser.ParseExpr(`map[int]int{1:2}`)ast.Print(nil, expr)}---------------------------output-------------------------18 . Elts: []ast.Expr (len = 1) {19 . . 0: *ast.KeyValueExpr {20 . . . Key: *ast.BasicLit {21 . . . . ValuePos: 1322 . . . . Kind: INT23 . . . . Value: "1"24 . . . }25 . . . Colon: 1426 . . . Value: *ast.BasicLit {27 . . . . ValuePos: 1528 . . . . Kind: INT29 . . . . Value: "2"30 . . . }31 . . }32 . }
map的初始值只能通过ast.KeyValueExpr对应的键值对表示,因为缺少了key无法定位值对应的下标位置。
