# 延迟调用 1

下面这个程序打印出什么？

    package main

    type Foo struct {
    	v int
    }

    func MakeFoo(n *int) Foo {
    	print(*n)
    	return Foo{}
    }

    func (Foo) Bar(n *int) {
    	print(*n)
    }

    func main() {
    	var x = 1
    	var p = &x
    	defer MakeFoo(p).Bar(p) // line 19
    	x = 2
    	p = new(int) // line 21
    	MakeFoo(p)
    }

选项：

- 100
- 102
- 022
- 011

答案：102

（在线运行之）

关键点：

- 当一个函数调用被推入延迟调用队列，被调用的函数值和所有实参（包括属主实参和普通实参）都将被估值。 这些估值将在此延迟调用在以后被执行的时候使用。
- 所以，在第 19 行，延迟 `Bar` 调用被推入延迟调用队列时，它的属主实参 `MakeFoo(p)` 和普通实参 `p` 被估值。 在估值（即调用） `MakeFoo(p)` 时，将打印出 `1`。
- 后来在第 21 行对变量 `p` 的修改不影响上述估值结果。 这意味着传递给 `Bar` 调用的普通实参依旧是一个指向变量 `x` 的指针。

一个类似的测验：

    package main

    type T int

    func (t T) M(n int) T {
    	print(n)
    	return t
    }

    func main() {
    	var t T
    	defer t.M(1).M(2)
    	t.M(3).M(4)
    }

上面这个程序打印出 `1342`。