以两种不同方式声明的变量的defer调用会产生不同的结果
Widget _reviewBody() {
return SliverToBoxAdapter(
child: Container(
width: 10.0,
padding: EdgeInsets.only(bottom: 30.0),
child: TextField(
onChanged: (text) {
setState(() {
reviewBody = text;
});
},
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(
hintText: 'Add your thoughts here',
hintStyle: TextStyle(color: Burnt.hintTextColor),
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Burnt.lightGrey)),
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Burnt.primaryLight, width: 1.0)),
),
textAlign: TextAlign.center,
),
),
);
}
答案 0 :(得分:7)
在第一个示例中,i
是一个(传入)参数。在return
语句中,计算返回值,然后执行延迟函数,然后递增i
对返回值没有影响。
在第二个示例中,i
是结果参数的名称。在return
语句中,您明确返回值i
,然后将其分配给返回值i
(这是一个空操作)。但是,允许延迟函数修改返回“变量”的值,如果这样做,则会对实际返回的值产生影响。
如果我们再添加一个示例,这将变得更清楚:
func c2() (i int) {
defer func() { i++ }()
return 2
}
此函数将返回3
,因为return 2
语句会将2
分配给i
,然后推迟的函数将对此递增,因此返回值将为3
。在Go Playground上尝试这个。 Spec: Return statements:
用于指定结果的“返回”语句在执行任何延迟函数之前会设置结果参数。
通常,如果函数(或方法)已命名结果参数,则返回值将始终是这些变量的值,但一定不要忘记return
语句可能会向这些结果参数分配新值,并且可以通过return
语句后的 延迟函数对其进行修改。
Spec: Defer statements中提到了这一点:
例如,如果延迟函数是function literal,而周围函数的named result parameters在文字范围内,则延迟函数可以在返回结果参数之前对其进行访问和修改。
博客文章Defer, Panic and Recover中也提到了该问题:
延迟的函数可以读取并分配给返回函数的命名返回值。
如果
doParse
出现紧急情况,恢复块会将返回值设置为nil
-延迟函数可以修改命名的返回值。