有返回值的函数,必须有明确的 return 终止语句。

除非有 panic,或者无 break 的死循环,则无须 return 终止语句。

func test(x int) int { 
	if x > 0 { 
	   return 1
	} else if x < 0 { 
	   return -1
	}
 
	for {
		break
	}
} // 错误:missing return at end of function

借鉴自动态语言的多返回值模式,函数得以返回更多状态,尤其是 error 模式。

稍有不便的是没有元组(tuple)类型,也不能用数组、切片接收,但可用 _ 忽略掉不想要的返回值。多返回值可用作其他函数调用实参,或当作结果直接返回。

func div(x, y int) (int, error) { // 多返回值列表必须使用括号
	if y == 0 { 
		return 0, errors.New("division by zero")
	} 
	
	return x / y, nil
}
  
func log(x int, err error) { 
   fmt.Println(x, err) 
} 
  
func test() (int, error) { 
   return div(5, 0) // 多返回值用作return结果 
} 
  
func main() {
	log(test()) // 多返回值用作实参
}

命名返回值

命名返回值让函数声明更加清晰,同时也会改善帮助文档和代码编辑器提示。

命名返回值和参数一样,可当作函数局部变量使用,最后由 return 隐式返回。

func div(x, y int) (z int, err error) { 
	if y == 0 { 
		err = errors.New("division by zero") 
		return
	} 
  
	z = x / y
	return // 相当于:return z, err
}

这些特殊的“局部变量”会被不同层级的同名变量遮蔽。好在编译器能检查到此类状况,只要改为显式 return 返回即可。

func add(x, y int) (z int) { 
	{ 
		z := x + y // 新定义的同名局部变量,同名遮蔽 
		return // 错误:z is shadowed during return(改成 "return z" 即可) 
	}
 
	return
}

除遮蔽外,我们还必须对全部返回值命名,否则编译器会搞不清状况。

func test() (int, s string, e error) { 
	return 0, "", nil
	// 错误:cannot use 0(type int)as type string in return argument
}