使用可变参数函数具有灵活性、重用性、简化调用等优点,各个语言有各自定义可变参数函数的方法,也有通用的处理方法,比如使用数组、定义参数结构体、使用泛型等。
这里总结记录一下 go、delphi 的常用的定义可变参数函数的方式!
一、Go 定义可变参数函数
- 定义方式:在类型前面加上省略号(
...
),如果将可变参数定义为...
interface{}
类型,则可传递任意类型的值给函数 - 代码示例:
package main
import (
"fmt"
)
// 定义一个带有可变参数sum的函数
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
func main() {
// 调用sum函数并传入可变数量的参数
fmt.Println(sum(1, 2, 3)) // 输出: 6
// 也可以通过一个切片来传递参数
numbers := []int{5, 6}
fmt.Println(sum(numbers...)) // 输出: 11
}
可变参数定义为 ...
interface{}
类型:
package main
import (
"fmt"
)
func printValues(values ...interface{}) {
for _, value := range values {
switch v := value.(type) {
case int:
fmt.Println(v, "is an int")
case string:
fmt.Println(v, "is a string")
default:
fmt.Println(v, "is of a different type")
}
}
}
func main() {
printValues(1, "two", 3.0)
}
- 注意事项:
①可变参数必须是函数参数列表中的最后一个参数
②调用函数传入切片时,需要在切片后加(...),否则只会将切片本身作为一个单独的参数传递给函数,而不是切片中的元素
③用 ...
interface{}作为参数类型时,需
使用类型断言来处理不同的类型
二、Delphi 定义可变参数函数
- 定义方式:使用数组(array of const),结合 TVarRec 结构体判断参数类型
- 代码示例:
type
//定义一个简单的类,用来作为测试可变参数函数的其中一个参数
TPerson = class
private
name: string;
end;
//定义该函数的参数为可变参数
procedure PrintMultipleParams(args: array of const);
//可变参数函数的实现部分
procedure PrintMultipleParams(args: array of const);
var
i: integer;
sInfo: string;
begin
sInfo := '';
for i := Low(args) to High(args) do
begin
// 通过 TVarRec().VType 判断参数的类型, TVarRec(args[i]).VInteger 取值
case TVarRec(args[i]).VType of
vtInteger:
sInfo := sInfo + '整形值: ' + IntToStr(TVarRec(args[i]).VInteger) + #13#10;
vtUnicodeString:
sInfo := sInfo + '字符串: ' + string(TVarRec(args[i]).VString) + #13#10;
vtObject: // 这里假定确定类为 TPerson ,获取 person.name
sInfo := sInfo + '类名: ' + TVarRec(args[i]).VObject.ClassName + ' -- '
+ TPerson(TVarRec(args[i]).VObject).name+ #13#10;
else
sInfo := sInfo + ' -- 不支持的类型';
end;
end;
ShowMessage(sInfo);
end;
//调用可变参数函数
procedure TForm1.btn1Click(Sender: TObject);
var
person: TPerson;
begin
// 传递 3 个参数
PrintMultipleParams([1, '测试可变参数', 3]);
// 传递 4 个参数
PrintMultipleParams([1, '测试可变参数', 3, '中国']);
// 传递 2 个参数
person := TPerson.Create;
try
person.name := '可变参数是 TObject';
PrintMultipleParams([1, person]);
finally
FreeAndNil(person);
end;
end
测试结果:
- 注意事项:
TVarRec 是 Delphi 中用于表示一个记录的类型,该记录有一个可以保存多种值的变体部分。这些值可以包括整数、布尔、字符、实数、字符串、指针、类、类引用、接口、变体等。
VType 字段用于表示记录值的类型,对应的值分别用 VInteger、VString、VObject等获取。
delphi 中 TVarRec 的定义如下:
TVarRec = record { do not pack this record; it is compiler-generated }
case Integer of
0: (case Byte of
vtInteger: (VInteger: Integer);
vtBoolean: (VBoolean: Boolean);
{$IFNDEF NEXTGEN}
vtChar: (VChar: _AnsiChr);
{$ENDIF !NEXTGEN}
vtExtended: (VExtended: PExtended);
{$IFNDEF NEXTGEN}
vtString: (VString: _PShortStr);
{$ENDIF !NEXTGEN}
vtPointer: (VPointer: Pointer);
{$IFNDEF NEXTGEN}
vtPChar: (VPChar: _PAnsiChr);
{$ENDIF !NEXTGEN}
{$IFDEF AUTOREFCOUNT}
vtObject: (VObject: Pointer);
{$ELSE}
vtObject: (VObject: TObject);
{$ENDIF}
vtClass: (VClass: TClass);
vtWideChar: (VWideChar: WideChar);
vtPWideChar: (VPWideChar: PWideChar);
{$IFNDEF NEXTGEN}
vtAnsiString: (VAnsiString: Pointer);
{$ENDIF !NEXTGEN}
vtCurrency: (VCurrency: PCurrency);
vtVariant: (VVariant: PVariant);
vtInterface: (VInterface: Pointer);
vtWideString: (VWideString: Pointer);
vtInt64: (VInt64: PInt64);
vtUnicodeString: (VUnicodeString: Pointer);
);
1: (_Reserved1: NativeInt;
VType: Byte;
);
end;