Go中的多值表达式

表达式描述了值的计算,它由操作符(标识符,文字,括号之间的另一个表达式,......)组成,它们应用于运算符或函数:

fmt.Println(1 + 2)
v:= 3
fmt.Println(v * 2)
fmt.Println(float64(v * 3)/ 2)
fmt.Println(map [string] int {“foo”:1} [ “foo”])
f:= func(n int)int {return n * 2}
g:= func()int {return 4}
fmt.Println(f(g()))

输出:

3 
6
4.5
1
8

我们在上面处理像算术公式这样的表达式,获得与map的键或函数调用相关的值。Golang支持更多。

多值表达

单个表达式可以一次返回多个值,然后称为多值表达式:

func f()(int,int){ 
return 1,2
}
func main(){
fmt.Println(f())
}

在上面的代码片段中,expression f()返回两个整数值 - 每个表达式在相应的return语句中用逗号分隔。的类型F公司

返回值不是状阵列或切片,但字面两个值:

fmt.Println(“%T”,f())

它给出了编译时错误multiple-value f() in single-value context,证明我们在这里处理的是多个值。

在return语句中不需要使用逗号分隔的表达式来从函数的调用中创建多值表达式 - 它也在使用命名结果参数时发生:

func f(a,b int)int { 
return a + b
}
func g()(a,b int){
a = 1
b = 2
return
}
func main(){
fmt.Println(f(g()))// 3
}

让我们看看它在行动中这个多值表达式可能实际上有用......

错误

标准库中的一个例子是io.Writer接口:

type Writer interface { 
Write(p [] byte)(n int,err error)
}

第一个返回值n返回写入的字节数,如果没有成功写入所有传递的字节,则err为非nil。另一个样本是无所不在的fmt.Println。Go中的惯用代码以这种方式处理错误 - 通过返回另一个非零的值,而不是一切都很好。

函数调用中的多值参数

多值表达式可以用作函数的参数,准确地接受该数量的参数及其各自的类型作为表达式。让我们看看它是如何工作的:

func f(a,b int)int { 
return a + b
}
func g()(int,int){
return 1,2
}
func main(){
fmt.Println(f(g()))// 3
}

表达g()是多值的。Golang允许在函数调用中使用这样的表达式,并且多值表达式的值将被传递给相应的参数。但是有一些限制:

  • g()必须至少有一个返回值。这似乎很清楚,否则我们可以传递一些不提供任何值的参数(源代码):
func f()int { 
return 1
}
func g(){
}
func main(){
fmt.Println(f(g()))
}

编译将抛出两个错误:g() used as value and too many arguments in call to f。

  • 只有多值表达式作为参数传递,并且可以使用一个这样的表达式(源代码):
func f(a,b,c int)int { 
return a + b + c
}
func g()(int,int){
return 1,2
}
func main(){
fmt.Println(f(g(),3))
}

建造时会出现两个错误:multiple-value g() in single-value context and not enough arguments in call to f。传递多个多值表达式也是如此:

func f(a,b,c,d int)int { 
return a + b + c + d
}
func g()(int,int){
return 1,2
}
func h()(int,int){
return 3,4

}
func main(){
fmt.Println(f(g(),h()))
}

可变函数

如果使用多值表达式调用的函数是可变参数,那么这样的表达式需要返回至少一个值:

func f(start int,nums ... int)int { 
sum:= start
for _,num:= range nums {
sum + = num
}
return sum
}
func g()int {return 1}
func h()(int,int){return 1,2}
func i()(int,int,int){return 1,2,3}
func main(){
fmt.Println(f(g()))// 1
fmt.Println(f(h()))// 3
fmt.Println(f(i()))// 6
}

如果我们将有func g() {}再调用f(g())会return g() used as value error试图编译程序。

return语句中的多值表达式

多亏了函数调用中的多值表达式处理,代码更简洁:

func f(a,b int)int { 
return a + b
}

func g()(int,int){
return 1,2
}
func main(){
a,b:= g()
fmt.Println(f(a,b))
fmt.Println(f(g()))
}

两个调用f(a, b)并f(g())具有相同的效果但前者需要使用元组赋值。

返回语句中可以使用类似的机制。如果使用多值函数调用,那么这样的return语句将返回多个值:

func f()(int,int){ 
return g()
}
func g()(int,int){
return 1,2
}
func main(){
fmt.Println(f())
}

其他多值表达式

除了return语句之外,还有其他可以创建多值表达式的地方。但是,只有在使用元组赋值时才会触发多值变体。让我们看看它如何与接收运算符一起工作(多值变体也有类型断言并从map中检索键值)。

多值接收运算符返回发送值(或元素类型的默认值)以及通道是否关闭的指示:

c:= make(chan int)
close(c)
_,ok:= fmt.Println(ok)// false

如前所述,多值版本的接收操作不能用于函数调用。只有元组赋值提示程序员想要访问两个值的编译器,否则编译器将采用单值版本:

func f(int,bool){}
func main(){
c:= make(chan int)
f(< - c)
}

它给出了编译错误:

not enough arguments in call to f
\thave (int)
\twant (int, bool)


分享到:


相關文章: