基础面值
面值是在程序代码中直接表示的值,其它的非零初始值只能由面值常量或常量表达式生成。比如表达式x+2*y的2就是面值,而x和y则不是面值而是标识符。Go语言规范明确定义了基础面值只有整数、浮点数、复数、符文和字符串几种类型。
type BasicLit struct {
ValuePos token.Pos // literal position
Kind token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
Value 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: 1
2 . Kind: STRING
3 . Value: "\"9527\""
4 }
标识符面值
type Ident struct {
NamePos token.Pos // identifier position
Name string // identifier name
Obj *Object // denoted object; or nil
}
func main() {
expr, _ := parser.ParseExpr(`x`)
ast.Print(nil, expr)
}
-------------------------------output-------------------------------
0 *ast.Ident {
1 . NamePos: 1
2 . Name: "x"
3 . Obj: *ast.Object {
4 . . Kind: bad
5 . . Name: ""
6 . }
7 }
ast.Object是一个相对复杂的结构,其中Kind用于描述标识符的类型:
const (
Bad ObjKind = iota // for error handling
Pkg // package
Con // constant
Typ // type
Var // variable
Fun // function or method
Lbl // label
)
Bad表示未知的类型,其它的分别对应Go语言中包、常量、类型、变量、函数和标号等语法结构。
复合面值
在基础面值,我们已经见过整数、浮点数、复数、符文和字符串等一些简单的面值。除了基础面值之外,还有结构体面值、map面值和函数面值等。本节讨论复合面值的语法树表示。
函数面值
func main() {
expr, _ := parser.ParseExpr(`func(){}`)
ast.Print(nil, expr)
}
---------------------------output-------------------------
0 *ast.FuncLit {
1 . Type: *ast.FuncType {
2 . . Func: 1
3 . . Params: *ast.FieldList {
4 . . . Opening: 5
5 . . . Closing: 6
6 . . }
7 . }
8 . Body: *ast.BlockStmt {
9 . . Lbrace: 7
10 . . Rbrace: 8
11 . }
12 }
函数面值的语法树由ast.FuncLit结构体表示,其中再由Type成员表示类型,Body成员表示函数体语句。
我们可以对比下ast.FuncLit和ast.FuncDecl结构体的差异:
type FuncLit struct {
Type *FuncType // function type
Body *BlockStmt // function body
}
type FuncDecl struct {
Doc *CommentGroup // associated documentation; or nil
Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name
Type *FuncType // function signature: parameters, results, and position of "func" keyword
Body *BlockStmt // function body; or nil for external (non-Go) function
}
复合类型面值语法
复合型面值的语法树通过ast.CompositeLit表示:
type CompositeLit struct {
Type Expr // literal type; or nil
Lbrace token.Pos // position of "{"
Elts []Expr // list of composite elements; or nil
Rbrace 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: 1
3 . . Len: *ast.Ellipsis {
4 . . . Ellipsis: 2
5 . . }
6 . . Elt: *ast.Ident {
7 . . . NamePos: 6
8 . . . Name: "int"
9 . . . Obj: *ast.Object {
10 . . . . Kind: bad
11 . . . . Name: ""
12 . . . }
13 . . }
14 . }
15 . Lbrace: 9
16 . Elts: []ast.Expr (len = 2) {
17 . . 0: *ast.BasicLit {
18 . . . ValuePos: 10
19 . . . Kind: INT
20 . . . Value: "1"
21 . . }
22 . . 1: *ast.KeyValueExpr {
23 . . . Key: *ast.BasicLit {
24 . . . . ValuePos: 12
25 . . . . Kind: INT
26 . . . . Value: "2"
27 . . . }
28 . . . Colon: 13
29 . . . Value: *ast.BasicLit {
30 . . . . ValuePos: 14
31 . . . . Kind: INT
32 . . . . Value: "3"
33 . . . }
34 . . }
35 . }
36 . Rbrace: 15
37 . Incomplete: false
38 }
复合面值语法树由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: 14
33 . Elts: []ast.Expr (len = 1) {
34 . . 0: *ast.KeyValueExpr {
35 . . . Key: *ast.Ident {
36 . . . . NamePos: 15
37 . . . . Name: "X"
38 . . . }
39 . . . Colon: 16
40 . . . Value: *ast.BasicLit {
41 . . . . ValuePos: 17
42 . . . . Kind: INT
43 . . . . Value: "1"
44 . . . }
45 . . }
46 . }
47 . Rbrace: 18
48 . Incomplete: false
49 }
结构体面值依然是通过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: 15
36 . . . Kind: INT
37 . . . 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: 13
22 . . . . Kind: INT
23 . . . . Value: "1"
24 . . . }
25 . . . Colon: 14
26 . . . Value: *ast.BasicLit {
27 . . . . ValuePos: 15
28 . . . . Kind: INT
29 . . . . Value: "2"
30 . . . }
31 . . }
32 . }
map的初始值只能通过ast.KeyValueExpr对应的键值对表示,因为缺少了key无法定位值对应的下标位置。