Go language variadic function, when to use the ellipsis (...)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

In one example today, it is not always possible to use the ellipsis to expand a slice when invoking a variadic function, and sometimes the compiler may make an error, and in order to clear the description of the problem, I use a few small examples step by step instructions.

1. Propose the hypothetical demand
What if you want to find the smallest one in a bunch of data?

If the type of data is int, then I can do this:

func MinimumInt(first int, others ...int) int {    minfirst    forvalue := range others {        ifvaluemin {            minvalue        }    }    returnmin}

The second parameter of the Minimumint function above is declared as: others. int, which indicates that this is a variable parameter that can be passed 0 or any number of int parameters, inside the chipmunk, it is represented as a slice. The first argument is declared only so that the caller must pass in at least one argument, if written

func MinimumInt(others ...intint {}

This function receives a mutable parameter, or even a length of 0 (that is, does not pass in the parameter), and it is clear that calling the function without passing in the parameter does not satisfy the proposed requirement.

For calls to the Minimumint function, you can do this in several ways:

Minimumint (Ten, the, +, $,2,3)  //1var sliceint = []int{Ten, the, +, $,2,3} minimumint (sliceint[0], sliceint[1], sliceint[2], sliceint[3], sliceint[4], sliceint[5])  //2Minimumint (sliceint[0], sliceint[1:]...)  //3

For the first invocation, the literal constants of type int are used directly as parameters, and all parameters except the first parameter inside the Minimumint function are placed into an int type slice for processing;
The second way of invocation, essentially the same as the first, but no longer use literal constants, and constructed an int type slice, using the element of the slice as the parameter;
The third method of invocation, in fact, can be seen as a simplified version of the second, except that the ellipsis (...) is used. From the Moving expansion section;

2. Perfect demand

In the above example, we only do the int type data processing, if the data is other types? Can a generic handler function be implemented to handle almost all types of data?

For this problem, in C + + is easy to solve by generics, go does not support this, but there is still a solution-null interface

Func Minimum ( Firstinterface{}, Rest ... interface{}) interface{} {min:= First     for_,value: = Range Rest {Switch value:=value. (type) { CaseInt:if value<min. (int) {min=value} CaseFloat64:if value<min. (float64) {min=value} Case string:if value<min. (string) {min=value}        }    }return min}

For the above function, declare its argument type as NULL interface interface{}, and return a value of interface{}, so that the function can receive any type of data, and for the second argument, the number of arguments is arbitrary. Then use non-check type assertions in the function to handle different types of data separately, and a switch statement based on the type switch is used here.

For the invocation of the minimum function, make some attempts first:

Minimum (Ten, the, +, $,2,3)  //1var sliceint = []int{Ten, the, +, $,2,3} Minimum (sliceint[0], sliceint[1], sliceint[2], sliceint[3], sliceint[4], sliceint[5])  //2Minimum (sliceint[0], sliceint[1:]...)  //3

In general, the calling method is consistent with the Minimumint function:
The first uses literal constants directly;
The second constructs the slices, using each element in turn
The third uses slices and attempts to automatically expand slices with ellipses to use each element

However, when we compile, we find that the compiler reported an error:

# command-line-arguments./test.go:14: cannot use sliceInt[1:] (type []intas type []interfacein argument to Minimum

This error occurs in the third invocation mode, and here is a bit strange, in the Minimumint function using the ellipsis to automatically expand a slice is normal ah!

So I changed the calling method to the following:

Minimum(sliceInt[0]sliceInt[1:])

The compilation is passed, but after this call does not get the minimum value in the data, the reason is explained later!

Then, in curiosity, I tried to change the way the Minimumint function was called as follows:

MinimumInt(sliceInt[0], sliceInt[1:])//不再使用省略号展开

To compile again, I get the following error prompt:

# command-line-arguments./test.go:15: cannot use sliceInt[1:] (type []intasintin argument to MinimumInt

From the tip, it is easy to draw a conclusion: the second parameter of the Minimumint function others in the compiler appears to be just an int type variable, although inside the Minimumint function it is an int type slice ([]int), So we need to use ellipses to expand a slice into one element when we pass in the parameter, so that parameter matching can be done (go does not support the default type conversion)

For the interface{} NULL interface, it can refer to any type of data, such as:

    varIint=Ten    varSliceint = []int{Ten, the, +, $,2,3}varSliceintz []int= [][]int{[]int{1,2,3}, []int{4,5,6}, []int{7,8,9}}varInter_a interface{} = I//int    varInter_b interface{} = Sliceint//[]int    varInter_c interface{} = Sliceintz//[][]int

Visible interface{} can refer to int type data, and can refer to []int type data and [][]int type data.

Some might think that interface{} can be used to refer to int data, then is []interface{} referring to []int type data?] Then do a test:

var inter_d []interface{} = sliceInt[:]

At compile time, the compiler reports an error:

# command-line-arguments./test.go:27: cannot use sliceInt[:] (type []intas type []interfacein assignment

Both of them are incompatible and cannot be directly assigned! But in common sense, it seems to be possible to do so? Why did you get an error?
The reason is that for Var inter_d []interface{} declaration, we are actually declaring a slice that can hold any type of value, but the SLICE definition statement is not, and for an already declared slice type, we can only define it in the following form:

var inter_d []interface{} = []interface{}{sliceIntz[0], sliceIntz[1], sliceIntz[2]}

This will not be an error, then speaking of here, for the minimum function of the error should also have an answer? We will change the way it is called as follows:

Minimum(sliceInt[0]sliceInt[1]sliceInt[2]sliceInt[3])

There is no error in this call! Because we've constructed a slice in the right way!

For the invocation of the minimum function, if it is written as follows:

Minimum(sliceInt[0]sliceInt[1:])

Although the compilation passes, it does not get the correct minimum value, because when we pass in the argument, we pass in a reference to a slice, instead of building a slice from a single value! Because interface{} itself refers to the []int type, although the type of reset is still []interface{}, the type of reset[0] has changed!

You can do a validation by changing the minimum function to the following form:

Func Minimum ( Firstinterface{}, Rest ... interface{}) interface{} {min:= FirstFmt. Printf ("%t\t%t\n", rest, rest[0])//Print type information     for_,value: = Range Rest {Switch value:=value. (type) { CaseInt:if value<min. (int) {min=value} CaseFloat64:if value<min. (float64) {min=value} Case string:if value<min. (string) {min=value}        }    }return min}

The first method of invocation:

fmt.Println(Minimum(sliceInt[0], sliceInt[1], sliceInt[2], sliceInt[3], sliceInt[4], sliceInt[5]))//结果为://[]interface {}    int//2

The second method of invocation:

fmt.Println(Minimum(sliceInt[0], sliceInt[1:]))//结果为://[]interface {}    []int//10

I do not know whether this explanation is reasonable, language expression may not be particularly clear, helpless thinking repeatedly, I think only this explanation a little more reasonable!

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.