博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go函数的可变长参数_如何在Go中使用可变参数函数
阅读量:2506 次
发布时间:2019-05-11

本文共 11650 字,大约阅读时间需要 38 分钟。

go函数的可变长参数

介绍 (Introduction)

A variadic function is a function that accepts zero, one, or more values as a single argument. While variadic functions are not the common case, they can be used to make your code cleaner and more readable.

可变参数函数是接受零,一个或多个值作为单个参数的函数。 尽管可变参数函数不是常见的情况,但是可以使用可变参数函数使您的代码更整洁,更具可读性。

Variadic functions are more common than they seem. The most common one is the Println function from the package.

可变参数功能比看起来更普遍。 最常见的一种是软件包中的Println函数。

func Println(a ...interface{}) (n int, err error)

A with a parameter that is preceded with a set of ellipses (...) is considered a variadic function. The ellipsis means that the parameter provided can be zero, one, or more values. For the fmt.Println package, it is stating that the parameter a is variadic.

甲与前面带有一组椭圆的参数( ... )被认为是一个可变参数函数。 省略号表示提供的参数可以是零,一个或多个值。 对于fmt.Println包,它说明参数a是可变参数。

Let’s create a program that uses the fmt.Println function and pass in zero, one, or more values:

让我们创建一个使用fmt.Println函数并传递零,一个或多个值的程序:

print.go
print.go
package mainimport "fmt"func main() {    fmt.Println()    fmt.Println("one")    fmt.Println("one", "two")    fmt.Println("one", "two", "three")}

The first time we call fmt.Println, we don’t pass any arguments. The second time we call fmt.Println we pass in only a single argument, with the value of one. Then we pass one and two, and finally one, two, and three.

第一次调用fmt.Println ,我们不传递任何参数。 第二次调用fmt.Println我们仅传递一个参数,值为one 。 然后我们通过onetwo ,最后是onetwothree

Let’s run the program with the following command:

让我们使用以下命令运行该程序:

  • go run print.go

    去运行print.go

We’ll see the following output:

我们将看到以下输出:

Output   
oneone twoone two three

The first line of the output is blank. This is because we didn’t pass any arguments the first time fmt.Println was called. The second time the value of one was printed. Then one and two, and finally one, two, and three.

输出的第一行为空白。 这是因为第一次fmt.Println时没有传递任何参数。 第二次打印one值。 然后是onetwo ,最后是onetwothree

Now that we have seen how to call a variadic function, let’s look at how we can define our own variadic function.

现在,我们已经了解了如何调用可变参数函数,让我们看一下如何定义自己的可变参数函数。

定义可变函数 (Defining a Variadic Function)

We can define a variadic function by using an ellipsis (...) in front of the argument. Let’s create a program that greets people when their names are sent to the function:

我们可以通过在参数前面使用省略号( ... )来定义可变参数函数。 让我们创建一个程序,当他们的名字发送给函数时,向他们打招呼:

hello.go
你好
package mainimport "fmt"func main() {    sayHello()    sayHello("Sammy")    sayHello("Sammy", "Jessica", "Drew", "Jamie")}func sayHello(names ...string) {    for _, n := range names {        fmt.Printf("Hello %s\n", n)    }}

We created a sayHello function that takes only a single parameter called names. The parameter is variadic, as we put an ellipsis (...) before the data type: ...string. This tells Go that the function can accept zero, one, or many arguments.

我们创建了一个sayHello函数,该函数仅接受一个名为names参数。 该参数是可变参数,因为我们在数据类型: ...string之前加了一个省略号( ... )。 这告诉Go函数可以接受零个,一个或多个参数。

The sayHello function receives the names parameter as a . Since the data type is a , the names parameter can be treated just like a slice of strings ([]string) inside the function body. We can create a loop with the operator and iterate through the slice of strings.

sayHello函数将names参数作为接收。 由于数据类型是 ,因此可以像对待函数体内的一部分字符串( []string )一样对待names参数。 我们可以使用运算符创建一个循环并遍历字符串切片。

If we run the program, we will get the following output:

如果运行程序,将得到以下输出:

Output   
Hello SammyHello SammyHello JessicaHello DrewHello Jamie

Notice that nothing printed for the first time we called sayHello. This is because the variadic parameter was an empty slice of string. Since we are looping through the slice, there is nothing to iterate through, and fmt.Printf is never called.

请注意,我们第一次调用sayHello并没有打印任何内容。 这是因为可变参数是string的空slice 。 由于我们正在遍历切片,因此没有任何要迭代的内容,并且永远不会调用fmt.Printf

Let’s modify the program to detect that no values were sent in:

让我们修改程序以检测未发送任何值:

hello.go
你好
package mainimport "fmt"func main() {    sayHello()    sayHello("Sammy")    sayHello("Sammy", "Jessica", "Drew", "Jamie")}func sayHello(names ...string) {    if len(names) == 0 {        fmt.Println("nobody to greet")        return    }    for _, n := range names {        fmt.Printf("Hello %s\n", n)    }}

Now, by using an , if no values are passed, the length of names will be 0, and we will print out nobody to greet:

现在,通过使用 ,如果不传递任何值,则names的长度将为0 ,并且我们将打印出nobody to greet

Output   
nobody to greetHello SammyHello SammyHello JessicaHello DrewHello Jamie

Using a variadic parameter can make your code more readable. Let’s create a function that joins words together with a specified delimiter. We’ll create this program without a variadic function first to show how it would read:

使用可变参数可以使您的代码更具可读性。 让我们创建一个将单词与指定的分隔符连接在一起的函数。 我们将首先创建不带有可变函数的程序,以显示其内容:

join.go
加入
package mainimport "fmt"func main() {    var line string    line = join(",", []string{"Sammy", "Jessica", "Drew", "Jamie"})    fmt.Println(line)    line = join(",", []string{"Sammy", "Jessica"})    fmt.Println(line)    line = join(",", []string{"Sammy"})    fmt.Println(line)}func join(del string, values []string) string {    var line string    for i, v := range values {        line = line + v        if i != len(values)-1 {            line = line + del        }    }    return line}

In this program, we are passing a comma (,) as the delimiter to the join function. Then we are passing a slice of values to join. Here is the output:

在此程序中,我们将逗号( , )作为分隔符传递给join函数。 然后,我们传递了一部分值进行联接。 这是输出:

Output   
Sammy,Jessica,Drew,JamieSammy,JessicaSammy

Because the function takes a slice of string as the values parameter, we had to wrap all of our words in a slice when we called the join function. This can make the code difficult to read.

由于该函数将一个字符串切片作为values参数,因此在调用join函数时,我们必须将所有单词包装在一个切片中。 这会使代码难以阅读。

Now, let’s write the same function, but we’ll use a variadic function:

现在,让我们编写相同的函数,但是我们将使用可变参数函数:

join.go
加入
package mainimport "fmt"func main() {    var line string    line = join(",", "Sammy", "Jessica", "Drew", "Jamie")    fmt.Println(line)    line = join(",", "Sammy", "Jessica")    fmt.Println(line)    line = join(",", "Sammy")    fmt.Println(line)}func join(del string, values ...string) string {    var line string    for i, v := range values {        line = line + v        if i != len(values)-1 {            line = line + del        }    }    return line}

If we run the program, we can see that we get the same output as the previous program:

如果运行该程序,则可以看到与先前程序得到的输出相同:

Output   
Sammy,Jessica,Drew,JamieSammy,JessicaSammy

While both versions of the join function do the exact same thing programmatically, the variadic version of the function is much easier to read when it is being called.

尽管两个版本的join函数在编程上都做完全相同的事情,但是函数的可变版本在调用时要容易得多。

可变参量顺序 (Variadic Argument Order)

You can only have one variadic parameter in a function, and it must be the last parameter defined in the function. Defining parameters in a variadic function in any order other than the last parameter will result in a compilation error:

函数中只能有一个可变参数,并且它必须是函数中定义的最后一个参数。 在可变参数函数中以除最后一个参数以外的其他任何顺序定义参数将导致编译错误:

join.go
加入
package mainimport "fmt"func main() {    var line string    line = join(",", "Sammy", "Jessica", "Drew", "Jamie")    fmt.Println(line)    line = join(",", "Sammy", "Jessica")    fmt.Println(line)    line = join(",", "Sammy")    fmt.Println(line)}func join(values ...string, del string) string {    var line string    for i, v := range values {        line = line + v        if i != len(values)-1 {            line = line + del        }    }    return line}

This time we put the values parameter first in the join function. This will cause the following compilation error:

这次我们将values参数首先放在join函数中。 这将导致以下编译错误:

Output   
./join_error.go:18:11: syntax error: cannot use ... with non-final parameter values

When defining any variadic function, only the last parameter can be variadic.

当定义任何可变参数时,只有最后一个参数可以可变。

爆炸论点 (Exploding Arguments)

So far, we have seen that we can pass zero, one, or more values to a variadic function. However, there will be occasions when we have a slice of values and we want to send them to a variadic function.

到目前为止,我们已经看到可以将零,一个或多个值传递给可变参数函数。 但是,在某些情况下,我们会有一部分价值,我们想将它们发送给可变参数函数。

Let’s look at our join function from the last section to see what happens:

让我们从最后一部分看我们的join函数,看看会发生什么:

join.go
加入
package mainimport "fmt"func main() {    var line string    names := []string{"Sammy", "Jessica", "Drew", "Jamie"}    line = join(",", names)    fmt.Println(line)}func join(del string, values ...string) string {    var line string    for i, v := range values {        line = line + v        if i != len(values)-1 {            line = line + del        }    }    return line}

If we run this program, we will receive a compilation error:

如果运行此程序,则会收到编译错误:

Output   
./join-error.go:10:14: cannot use names (type []string) as type string in argument to join

Even though the variadic function will convert the parameter of values ...string to a slice of strings []string, we can’t pass a slice of strings as the argument. This is because the compiler expects discrete arguments of strings.

即使可变参数函数会将values ...string的参数转换为字符串[]string ,我们也无法将字符串的一部分作为参数传递。 这是因为编译器期望字符串的离散参数。

To work around this, we can explode a slice by suffixing it with a set of ellipses (...) and turning it into discrete arguments that will be passed to a variadic function:

要解决此问题,我们可以通过在切片上加上一组省略号( ... )并将其转换为离散的参数(将传递给可变参数)来使其爆炸

join.go
加入
package mainimport "fmt"func main() {    var line string    names := []string{"Sammy", "Jessica", "Drew", "Jamie"}    line = join(",", names...)    fmt.Println(line)}func join(del string, values ...string) string {    var line string    for i, v := range values {        line = line + v        if i != len(values)-1 {            line = line + del        }    }    return line}

This time, when we called the join function, we exploded the names slice by appending ellipses (...).

这次,当我们调用join函数时,我们通过附加省略号( ... )来分解names切片。

This allows the program to now run as expected:

这使程序现在可以按预期运行:

Output   
Sammy,Jessica,Drew,Jamie

It’s important to note that we can still pass a zero, one, or more arguments, as well as a slice that we explode. Here is the code passing all the variations that we have seen so far:

重要的是要注意,我们仍然可以传递零,一个或多个参数,以及爆炸的切片。 这是传递到目前为止我们看到的所有变化的代码:

join.go
加入
package mainimport "fmt"func main() {    var line string    line = join(",", []string{"Sammy", "Jessica", "Drew", "Jamie"}...)    fmt.Println(line)    line = join(",", "Sammy", "Jessica", "Drew", "Jamie")    fmt.Println(line)    line = join(",", "Sammy", "Jessica")    fmt.Println(line)    line = join(",", "Sammy")    fmt.Println(line)}func join(del string, values ...string) string {    var line string    for i, v := range values {        line = line + v        if i != len(values)-1 {            line = line + del        }    }    return line}
Output   
Sammy,Jessica,Drew,JamieSammy,Jessica,Drew,JamieSammy,JessicaSammy

We now know how to pass zero, one, or many arguments, as well as a slice that we explode, to a variadic function.

现在,我们知道如何将零个,一个或多个参数以及爆炸的切片传递给可变参数函数。

结论 (Conclusion)

In this tutorial, we have seen how variadic functions can make your code cleaner. While you won’t always need to use them, you may find them useful:

在本教程中,我们已经看到了可变参数函数如何使您的代码更整洁。 尽管您并不总是需要使用它们,但您可能会发现它们很有用:

  • If you find that you’re creating a temporary slice just to pass to a function.

    如果发现正在创建一个临时切片,只是要传递给函数。
  • When the number of input params are unknown or will vary when called.

    当输入参数的数量未知或调用时会有所不同。
  • To make your code more readable.

    使代码更具可读性。

To learn more about creating and calling functions, you can read .

要了解有关创建和调用函数的更多信息,可以阅读 。

翻译自:

go函数的可变长参数

转载地址:http://dthgb.baihongyu.com/

你可能感兴趣的文章
apache下虚拟域名配置
查看>>
session和cookie区别与联系
查看>>
PHP 实现笛卡尔积
查看>>
Laravel中的$loop
查看>>
CentOS7 重置root密码
查看>>
Centos安装Python3
查看>>
PHP批量插入
查看>>
laravel连接sql server 2008
查看>>
Laravel框架学习笔记之任务调度(定时任务)
查看>>
laravel 定时任务秒级执行
查看>>
浅析 Laravel 官方文档推荐的 Nginx 配置
查看>>
Swagger在Laravel项目中的使用
查看>>
Laravel 的生命周期
查看>>
CentOS Docker 安装
查看>>
Nginx
查看>>
Navicat远程连接云主机数据库
查看>>
Nginx配置文件nginx.conf中文详解(总结)
查看>>
MySQL innert join、left join、right join等理解
查看>>
sdc时序约束
查看>>
NoC片上网络
查看>>