Go 语言编程

函数多返回值

目前的主流语言中除Python外基本都不支持函数的多返回值功能,不是没有这类需求,可能是语言设计者没有想好该如何提供这个功能,或者认为这个功能会影响语言的美感。

比如我们如果要定义一个函数用于返回个人名字信息,而名字信息因为包含多个部分—姓氏、名字、中间名和别名,在不支持多返回值的语言中我们有以下两种做法:要么专门定义一个结构体用于返回,比如:

struct name 
{ 
  char first_name[20]; 
  char middle_name[20]; 
  char last_name[20]; 
  char nick_name[48]; 
}; 
// 函数原型
extern name get_name(); 

// 函数调用
name n = get_name();

或者以传出参数的方式返回多个结果:

// 函数原型
extern void get_name( 
  /*out*/char* first_name,  
  /*out*/char* middle_name,  
  /*out*/char* last_name,  
  /*out*/char* nick_name); 

// 先分配内存
char first_name[20]; 
char middle_name[20]; 
char last_name[20];  
char nick_name[48]; 
// 函数调用
get_name(first_name, middle_name, last_name, nick_name);

Go语言革命性地在静态开发语言阵营中率先提供了多返回值功能。这个特性让开发者可以从原来用各种比较别扭的方式返回多个值的痛苦中解脱出来,既不用再区分参数列表中哪几个用于输入,哪几个用于输出,也不用再只为了返回多个值而专门定义一个数据结构。

在Go语言中,上述的例子可以修改为以下的样子:

func getName()(firstName, middleName, lastName, nickName string){ 
    return "May", "M", "Chen", "Babe" 
}

因为返回值都已经有名字,因此各个返回值也可以用如下方式来在不同的位置进行赋值,从而提供了极大的灵活性:

func getName()(firstName, middleName, lastName, nickName string){ 
    firstName = "May" 
    middleName = "M" 
    lastName = "Chen" 
    nickName = "Babe" 
    return 
}

并不是每一个返回值都必须赋值,没有被明确赋值的返回值将保持默认的空值。而函数的调用相比C/C++语言要简化很多:

fn, mn, ln, nn := getName()

如果开发者只对该函数其中的某几个返回值感兴趣的话,也可以直接用下划线作为占位符来忽略其他不关心的返回值。下面的调用表示调用者只希望接收lastName的值,这样可以避免声明完全没用的变量:

_, _, lastName, _ := getName()

我们会在第二章中详细讲解多重返回值的用法。