Google News
logo
Golang Interview Questions
Go (or) Golang the popular and open-source programming language, It was initially developed at Google Inc. in 2007. Go programming language is designed by Robert Griesemer, Rob Pike and Ken Thompson. It is very strongly and staticall typed programming language used for building fast and reliable applications.
 
Golang was First appeared in November 10, 2009
* Unlike other languages which started as academic experiments, Go code is pragmatically designed. Every feature and syntax decision is engineered to make life easier for the programmer.
 
* Golang is optimized for concurrency and works well at scale.
 
* Golang is often considered more readable than other languages due to a single standard code format.
 
* Automatic garbage collection is notably more efficient than Java or Python because it executes concurrently alongside the program.
Packages (pkg) are directories within your Go workspace that contain Go source files or other packages. Every function, variable, and type from your source files are stored in the linked package. Every Go source file belongs to a package, which is declared at the top of the file using :
package <packagename>
You can import and export packages to reuse exported functions or types using :
import <packagename>
Golang’s standard package is fmt, which contains formatting and printing functionalities like Println().
A string literal is a string constant formed by concatenating characters. The two forms of string literal are raw and interpreted string literals.
 
Raw string literals are written within backticks (foo) and are filled with uninterpreted UTF-8 characters. Interpreted string literals are what we commonly think of as strings, written within double quotes and containing any character except newline and unfinished double quotes.
Golang uses the following types :

* Array
* String
* Method
* Boolean
* Numeric
* Interface
* Pointer
* Slice
* Struct
* Function
* Map
* Channel
A Goroutine is a function or procedure that runs concurrently with other Goroutines on a dedicated Goroutine thread. Goroutine threads are lighter than ordinary threads, and most Golang programs use thousands of goroutines at the same time. A Goroutine can be stopped by passing it a signal channel. Because Goroutines can only respond to signals if they are taught to check, you must put checks at logical places, such as at the top of your for a loop.
A string literals specifies a string constant that is obtained from concatenating a sequence of characters.
 
There are two types of string literals :
 
Raw string literals : The value of raw string literals are character sequence between back quotes ". Its value is specified as a string literal that composed of the uninterrupted character between quotes.

Interpreted string literals : It is shown between double quotes " ". The value of the literal is specified as text between the double quotes which may not contain newlines.
A workspace contains Go code. A workspace is a directory hierarchy with three directories at its root.
 
* "src" directory contains GO source files organized into packages.
* "pkg" directory contains package objects.
* "bin" directory contains executable commands
Static type variable declaration gives confirmation to the compiler that there is one variable existing with the given kind and name so the compiler continues for an additional compilation without requiring total insight concerning the variable. A variable declaration holds its importance at the moment of compilation only, the compiler requires actual variable declaration at the moment of connecting to the program.
A dynamic kind variable declaration needs the compiler to explain the kind of the variable based on the amount transferred to it. The compiler doesn’t need a variable to cateGorise statically as a mandatory condition.
func swap(sw []int) {

        for a, b := 0, len(sw)-1; a < b; a, b = a+1, b-1 {

                sw[a], sw[b] = sw[b], sw[a]

        }

}
func main() {

	x := []int{3, 2, 1}

	swap(x)

	fmt.Println(x)

	// Output: [1 2 3]

}
Go Pointers are those variables that hold the address of any variables. Due to this, they are called special variables. Pointers support two operators:
 
 *  operator : This operator is called a dereferencing operator and is used for accessing the value in the address stored by the pointer.

 &  operator : This operator is called the address operator and is used for returning the address of the variable stored in the pointer.
This is illustrated in the diagram below. Here, consider we have a variable x assigned to 100. We store x in the memory address 0x0201. Now, when we create a pointer of the name Y for the variable x, we assign the value as  &x  for storing the address of variable x. The pointer variable is stored in address 0x0208. Now to get the value stored in the address that is stored in the pointer, we can just write int z:= *Y

Pointers are used for the following purposes :
 
* Allowing function to directly mutate value passed to it. That is achieving pass by reference functionality.

* For increasing the performance in the edge cases in the presence of a large data structure. Using pointers help to copy large data efficiently.

* Helps in signifying the lack of values. For instance, while unmarshalling JSON data into a struct, it is useful to know if the key is present or absent then the key is present with 0 value.

The variable scope is defined as the part of the program where the variable can be accessed. Every variable is statically scoped (meaning a variable scope can be identified at compile time) in Go which means that the scope is declared at the time of compilation itself. There are two scopes in Go, they are:
 
Local variables : These are declared inside a function or a block and is accessible only within these entities.

Global variables : These are declared outside function or block and is accessible by the whole source file.
The Type Switch is the best way to check a variable’s type at runtime. The Type Switch evaluates variables by type rather than value. Each Switch contains at least one case, which acts as a conditional statement, and a default case, which executes if none of the cases are true.
 
For example, you could create a Type Switch that checks if interface value i contains the type int or string:
package main

import "fmt"

func do(i interface{}) {
	switch v := i.(type) {
	case int:
		fmt.Printf("Double %v is %v\n", v, v*2)
	case string:
		fmt.Printf("%q is %v bytes long\n", v, len(v))
	default:
		fmt.Printf("I don't know  type %T!\n", v)
	}
}

func main() {
	do(21)
	do("hello")
	do(true)
}
 
Output : 
Double 21 is 42
"hello" is 5 bytes long
I don't know  type bool!
A goroutine is a function or method that executes concurrently alongside any other goroutines using a special goroutine thread. Goroutine threads are more lightweight than standard threads, with most Golang programs using thousands of goroutines at once.
 
To create a goroutine, add the  go  keyword before the function declaration.
go f(x, y, z)
You can stop a goroutine by sending it a signal channel. Goroutines can only respond to signals if told to check, so you’ll need to include checks in logical places such as at the top of your for loop.
package main
func main() {
  quit := make(chan bool)
  go func() {
    for {
        select {
        case <-quit:
            return
        default:
            // …
        }
  }
}()
// …
quit <- true
}
Advantages/ Benefits of Go programming language :
 
* Go is fast and compiles very quickly.
* It supports concurrency at the language level.
* It has Garbage collection.
* It supports various safety features and CSP-style concurrent programming features.
* Strings and Maps are built into the language.
* Functions are first class objects in this language.
A list of built-in supports in Go :
 
Container : container/list,container/heap
Web Server : net/http
Cryptography : Crypto/md5 ,crypto/sha1
Compression : compress/ gzip
Database : database/sql
Yes. Multiple values can be returned in Golang by sending comma-separated values with the return statement and by assigning it to multiple variables in a single statement as shown in the example below:
package main
import (
	"fmt"
)

func reverseValues(a,b string)(string, string){
    return b,a    //notice how multiple values are returned
}

func main(){
    val1,val2:= reverseValues("freetime","learning")    // notice how multiple values are assigned
    fmt.Println(val1, val2)
}
In the above example, we have a function reverseValues which simply returns the inputs in reverse order. In the main goroutine, we call the reverseValues function and the values are assigned to values val1 and val2 in one statement. The output of the code would be
learning freetime
Yes, GoLang is case sensitive which intimates in Go
 
'ab' and 'AB' are diverse from each other and it doesn't disclose any error if we list these couple of variables in the same code.
Slice in Go is a lightweight data structure of variable length sequence for storing homogeneous data. It is more convenient, powerful and flexible than an array in Go. Slice has 3 components:
 
Pointer : This is used for pointing to the first element of the array accessible via slice. The element doesn’t need to be the first element of the array.
Length : This is used for representing the total elements count present in the slice.
Capacity : This represents the capacity up to which the slice can expand.

For example : Consider an array of name arr having the values “This”,“is”, “a”,“Go”,“interview”,“question”.
package main
 
import "fmt"
 
func main() {
 
    // Creating an array
    arr := [6]string{"This","is", "a","Go","interview","question"}
 
    // Print array
    fmt.Println("Original Array:", arr)
 
    // Create a slice
    slicedArr := arr[1:4]
 
    // Display slice
    fmt.Println("Sliced Array:", slicedArr)
 
    // Length of slice calculated using len()
    fmt.Println("Length of the slice: %d", len(slicedArr))
 
    // Capacity of slice calculated using cap()
    fmt.Println("Capacity of the slice: %d", cap(slicedArr))
}
Here, we are trying to slice the array to get only the first 3 words starting from the word at the first index from the original array. Then we are finding the length of the slice and the capacity of the slice. The output of the above code would be :
Original Array: [This is a Go interview question]
Sliced Array: [is a Go]
Length of the slice: %d 3
Capacity of the slice: %d 5
There are 4 data types in the Go language
 
* Basic type numbers, strings, and booleans
* Aggregate type structures and arrays
* Reference type slices, pointers, maps, channels, and functions
* Interface type
There is only one difference between Go methods and Go functions that is the methods of Golang contain receiver argument in them. The method can obtain the characteristics of the receiver with the cooperation of the receiver argument.
 
Syntax :
func(name type) method_name(param_list)(return_type)

{

     //code

}
The easiest way to concatenate strings is to use the concatenation operator (+), which allows you to add strings as you would numerical values.
package main
import "fmt"
  
func main() { 
  
    // Creating and initializing strings 
    // using var keyword 
    var str1 string 
    str1 = "Hello "
  
    var str2 string 
    str2 = "Reader!"
  
    // Concatenating strings 
    // Using + operator 
    fmt.Println("New string 1: ", str1+str2) 
  
    // Creating and initializing strings 
    // Using shorthand declaration 
    str3 := "Welcome"
    str4 := "FreetimeLearning.com"
  
    // Concatenating strings 
    // Using + operator 
    result := str3 + " to " + str4 
  
    fmt.Println("New string 2: ", result) 
  
} 
 
Output : 
New string 1:  Hello Reader!
New string 2:  Welcome to FreetimeLearning.com
The syntax of a for loop in Go programming language is :

for [condition |  ( init; condition; increment ) | Range]  
{  
   statement(s);  
}  
Syntax to create a function in Go :
 
func function_name( [parameter list] ) [return_types]  
{  
   body of the function  
}
A pointer is used to hold the address of a variable.
 
For example :

var x = 5  
var p *int  
p = &x  
fmt.Printf("x = %d", *p)  
Here x can be accessed by *p.​
The GO programming language syntax is specified using Extended Backus-Naur Form (EBNF) :
 
* Production = production_name "=" [ Expression ]
* Expression = Alternative { "l" Alternative }
* Alternative = Term { Term }
* Term = Production_name l token [ "?"token] l Group l Option l Repetition
* Group = " ( "" Expression")"
* Option = " [ " Expression "" ]"
* Repetition = " {" Expression "}"
In GO, interfaces is a way to identify the behavior of an object. An interface is created by using the "type" word, followed by a name and the keyword interface. An interface is specified as two things.
 
* A set of methods.
* Also it is referred as type.
Golang supports automated testing of packages with custom testing suites.
 
To create a new suite, create a file that ends with _test.go and includes a TestXxx function, where Xxx is replaced with the name of the feature you’re testing. For example, a function that tests login capabilities would be called TestLogin.
 
You then place the testing suite file in the same package as the file you wish to test. The test file will be skipped on regular execution but will run when you enter the go test command.
Function closures is a function value that references variables from outside its body. The function may access and assign values to the referenced variables.
 
For example : adder() returns a closure, which is each bound to its own referenced sum variable.

package main

import "fmt"

func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func main() {
	pos, neg := adder(), adder()
	for i := 0; i < 10; i++ {
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	}
}​

Output :

0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90

 

This is a bit of a trick question : there is no inheritance in Golang because it does not support classes.
 
However, you can mimic inheritance behavior using composition to use an existing struct object to define a starting behavior of a new object. Once the new object is created, functionality can be extended beyond the original struct.
type Animal struct {
    // …
}

func (a *Animal) Eat()   { … }
func (a *Animal) Sleep() { … }
func (a *Animal) Run() { … }

type Dog struct {
    Animal
    // …
}
The Animal struct contains Eat(), Sleep(), and Run() functions. These functions are embedded into the child struct Dog by simply listing the struct at the top of the implementation of Dog.
Lvalue
 
* Refers to a memory location
 
* Represents a variable identifier
 
* Mutable
 
* May appear on the left or right side of the = operator
 
For example : In the statement x =20, x is an lvalue and 20 is an rvalue.
 
Rvalue
 
* Represents a data value stored in memory
 
* Represents a constant value
 
* Always appears on the = operator’s right side.
 
For example : The statement 10 = 20 is invalid because there is an rvalue (10) left of the = operator.
This is an important Golang interview question. Go is an attempt to create a new, concurrent, garbage-collected language with quick compilation and the following advantages :
 
* On a single machine, a big Go application can be compiled in a matter of seconds.

* Go provides an architecture for software development that simplifies dependency analysis while avoiding much of the complexity associated with C-style programs, such as files and libraries.

* Because there is no hierarchy in Go's type system, no work is wasted describing the relationships between types. Furthermore, while Go uses static types, the language strives to make types feel lighter weight than in traditional OO languages.

* Go is fully garbage-collected and supports parallel execution and communication at a fundamental level.

* Go's design presents a method for developing system software on multicore processors.

The sender will block on an unbuffered channel until the receiver receives data from the channel, and the receiver will block on the channel until the sender puts data into the channel.

The sender of the buffered channel will block when there is no empty slot on the channel, however, the receiver will block on the channel when it is empty, as opposed to the unbuffered equivalent.

Fmt in Golang is a package that is used for handling input received from the user. It has functions to accept the data and can display it to another location. It has functions like Printf, Println, Scanf, etc. It has format templates to provide the user with some prompts about the text that they have to type in.
The GOPATH is an environment variable that is used for listing the places for looking for Go code. It specifies the directories that are outside GOROOT that have source code.

The GOROOT is an environment variable that specifies the directory where Golang is installed.
A rune is a Unicode endpoint that is basically a literal for 32-bit integers. They can be altered ad they are untyped constants.
 
It can represent the following :
 
* An integer value ranging from 0 to 2^32-1.
* A character.
* A keyword rune that is a Golang type. It is an alias of the int32 type.
Go has only one looping construct: the for loop. The for loop has 3 components separated by semicolons:
 
The Init statement, which is executed before the loop begins. It’s often a variable declaration only visible within the scope of the for loop.
 
The condition expression, which is evaluated as a Boolean before each iteration to determine if the loop should continue.
 
The post statement, which is executed at the end of each iteration.
package main
import "fmt"
func main() {
    sum := 0
    for i := 0; i < 10; i++ {
        sum += i
    }
    fmt.Println(sum)
}
Output :
45
Yes. A Go function can return multiple values, each separated by commas in the return statement.
package main

import "fmt"

func foo() (string, string) {
   return "two", "values"
}

func main() {
   fmt.Println(foo())

}​
Output : 
two values
Implement a stack structure with pop, append, and print top functionalities.
 
Solution
 
You can implement a stack using a slice object.
package main

import "fmt"

func main() {

// Create

var stack []string

// Push

stack = append(stack, "world!")

stack = append(stack, "Hello ")

for len(stack) > 0 {

        // Print top

        n := len(stack) - 1

        fmt.Print(stack[n])

        // Pop

        stack = stack[:n]

}

// Output: Hello world!

}​

Output : 

Hello world!

 

First, we use the built-in append() function to implement the append behavior. Then we use len(stack)-1 to select the top of the stack and print.

For pop, we set the new length of the stack to the position of the printed top value, len(stack)-1.

 

Implement the perm() function that accepts a slice or string and prints all possible combinations of characters.
 
Solution
package main
import "fmt"

// Perm calls f with each permutation of a.

func Perm(a []rune, f func([]rune)) {
        perm(a, f, 0)
}

// Permute the values at index i to len(a)-1.

func perm(a []rune, f func([]rune), i int) {
        if i > len(a) {
                f(a)
                return
        }
        perm(a, f, i+1)
        for j := i + 1; j < len(a); j++ {
                a[i], a[j] = a[j], a[i]
                perm(a, f, i+1)
                a[i], a[j] = a[j], a[i]
        }
}

func main() {
Perm([]rune("abc"), func(a []rune) {
        fmt.Println(string(a))
})
}
Output : 
abc
acb
bac
bca
cba
cab
We use rune types to handle both slices and strings. Runes are Unicode code points and can therefore parse strings and slices equally.
Once the values are stored in key-value pairs in the map, we can retrieve the object by using the key as map_name[key_name] and we can check if the key, say “foo”, is present or not and then perform some operations by using the below code:
if val, ok := dict["foo"]; ok {
    //do something here
}
Explanation :
if statements in Go can include both a condition and an initialization statement. 
 
* initializes two variables - val will receive either the value of "foo" from the map or a "zero value" (in this case the empty string) and ok will receive a bool that will be set to true if "foo" was actually present in the map
 
* evaluates ok, which will be true if "foo" was in the map
 
If "foo" is indeed present in the map, the body of the if statement will be executed and val will be local to that scope.
/DemoStruct definition
type DemoStruct struct {
    Val int
}
//A.
func demo_func() DemoStruct {
    return DemoStruct{Val: 1}
}
//B.
func demo_func() *DemoStruct {
    return &DemoStruct{}
}
//C.
func demo_func(s *DemoStruct) {
    s.Val = 1
}
A. Since the function has a return type of the struct, the function returns a copy of the struct by setting the value as 1.
B. Since the function returns *DemoStruct, which is a pointer to the struct, it returns a pointer to the struct value created within the function.
C. Since the function expects the existing struct object as a parameter and in the function, we are setting the value of its attribute, at the end of execution the value of Val variable of the struct object is set to 1.
In Go, the errors are nothing but an interface type where any type implementing the single Error() method is considered as an error. Go does not have try/catch methods as in other programming languages for handling the errors. They are instead returned as normal values. Following is the syntax for creating the error interface:
type error_name interface {
    Error() string
}
We use this whenever we apprehend that there are possibilities where a function can go wrong during type conversions or network calls. The function should return an error as its return variable if things go wrong. The caller has to check this error value and identify the error. Any value other than nil is termed as an error.
 
As part of good error handling practices, guard classes should be used over if-else statements. They should also be wrapped in a meaningful way as they can be passed up in the call stack. Errors of the same types should not be logged or handled multiple times.
There are 4 decision-making statements in Golang they are
 
if statement : used to decide whether certain statements will be executed or not 

if-else statement : if a certain condition is true only then it will execute a block if it is not true then it won’t execute the block of code

Nested-if statement : nested if means if condition inside another 

if condition
if-else-if ladder : Here, a user can choose among various options. The if statements are executed of top-down. As early as one of the states controlling the if is correct, the statement compared with that if is executed, and the remaining ladder is bypassed. If none of the conditions is correct, then the last else statement will be executed.
The break statement is utilized to stop the for loop or switch statement and assign execution to the statement quickly following the for loop or switch.
The continued statement promotes the loop to bound the remains of its body and quickly retest its state preceding to repeating.
A channel is a communication medium through which a Goroutine communicates with different Goroutine and this communication is lock-free. Practically, in other words, a channel is a method that enables an individual Goroutine to send data to a different Goroutine. 
A switch statement is a multi-way branch record. It gives an effective way to assign the execution to various parts of code based upon the utility of the expression. Go language holds two types of switch statements they are
 
Expression switch : expression switch in Golang is the same as the switch statement in C, C++, Java languages, It gives an effortless way to dispatch execution to various parts of code which is based upon the value of the phrase.
 
Syntax :
switch optstatement; optexpression

{

case exp1: statement

case exp2: statement

…..

default: statement

}

Type switch :
A Type switch is utilized when you require to match types. In this switch, the case includes the type which is operating to compare with the type existing in the switch expression.
 
Syntax :
switch optstatement; type switchexpression

{

case type1: statement

case type2: statement

…..

default: statement

}
CGo allows Go packages to invite C code. Given a Go source file that is written with some unique features, cGo yields Go and C files that can be merged into a unique Go package. That is because C means a "pseudo-package", a unique name defined by cGo as a reference to C's namespace.
Go is a Post-OOP programming language that borrows the structure (functions, packages, types) from the Pascal/Algol/Modula language family. In Go, object-oriented patterns are still helpful to structure a program in a clear and understandable way.
Golang supports two kinds of expressions:
 
lvalue : The expressions which are referred to as memory locations are known as "lvalue" expressions. It appears either on the right-hand or left-hand side of an assignment operator.
 
rvalue : It refers to a data value that is stored at some address in memory. It cannot have a value assigned to it. So rvalues always appear on the right side of the assignment operator.
Implement swap() which swaps the value of two variables without using a third variable.
 
Example : 
package main

import "fmt"

func main() {
   fmt.Println(swap())
}

func swap() []int {
      a, b := 15, 10
   b, a = a, b
   return []int{a, b}
}

Output :

[10 15]

 

While this may be tricky in other languages, Go makes it easy.

We can simply include the statement b, a = a, b, what data the variable references without engaging with either value.

Implement Min(x, y int) and Max(x, y int) functions that take two integers and return the lesser or greater value, respectively.
 
Example :
By default, Go only supports min and max for floats using math.min and math.max. You’ll have to create your own implementations to make it work for integers.
package main

import "fmt"

// Min returns the smaller of x or y.

func Min(x, y int) int {
        if x > y {
                return y
        }
        return x
}

// Max returns the larger of x or y.

func Max(x, y int) int {
        if x < y {
                return y
        }
        return x
}

func main() { 
    fmt.Println(Min(5,10))
    fmt.Println(Max(5,10))
}​

Output :

5
10

 

Shadowing is a principle when a variable overrides a variable in a more specific scope. This means that when a variable is declared in an inner scope having the same data type and name in the outer scope, the variable is said to be shadowed. The outer variable is declared before the shadowed variable.
 
Consider a code snippet as shown below :
var numOfCars = 2    // Line 1
type Car struct{
	name string
	model string
	color string
}
cars:= [{
            name:"Toyota",
            model:"Corolla",
            color:"red"
        },
        {
	    name:"Toyota",
            model:"Innova",
            color:"gray"
	}]

func countRedCars(){
    for i:=0; i<numOfCars; i++{
	if cars[i].color == "red" {
		numOfCars +=1    // Line 2
		fmt.Println("Inside countRedCars method ", numOfCars)    //Line 3
	}
    }	    
}
Here, we have a function called countRedCars where we will be counting the red cars. We have the numOfCars variable defined at the beginning indicated by the Line 1  comment. Inside the countRedCars method, we have an if statement that checks whether the colour is red and if red then increments the numOfCars by 1. The interesting point here is that the value of the numCars variable after the end of the if statement will not be affecting the value of the numOfCars variable in the outer scope.
To find the nth Fibonacci number, we have to add the previous 2 Fibonacci numbers as shown below.
fib(0)=0
fib(1)=1
fib(2)=1+0 = 1
fib(3)=1+1 = 2
fib(4)=2+1 = 3
: 
: 
fib(n)=fib(n-1)+fib(n-2)
Code :
package main
import "fmt"
//nth fibonacci number function
func fibonacci(n int) int {
        if n < 2 {
            return n
        }
        return fibonacci(n-1) + fibonacci(n-2)
}

func main() {
    fmt.Println(fibonacci(7))
}
Output :
13
Find the easiest way to format a string with variables without printing the value.
 
Solution : The easiest way to format without printing is to use the fmt.Sprintf(), which returns a string without printing it.
 
For example :
package main

import "fmt"

func main() {
  s := fmt.Sprintf("Size: %d MB.", 90)
  fmt.Println(s)
}

Output : 

Size: 90 MB.

 

Command-line arguments are a way to provide the parameters or arguments to the main function of a program. Similarly, In Go, we use this technique to pass the arguments at the run time of a program.
 
In Golang, we have a package called as os package that contains an array called as “Args”. Args is an array of string that contains all the command line arguments passed.
 
The first argument will be always the program name as shown below.
 
Example :  Try to use offline compiler for better results. Save the below file as cmdargs1.go

// Golang program to show how
// to use command-line arguments
package main
  
import (
    "fmt"
    "os"
)
  
func main() {
  
    // The first argument
    // is always program name
    myProgramName := os.Args[0]
      
    // it will display 
    // the program name
    fmt.Println(myProgramName)
}

Output : Here, you can see it is showing the program name with full path. Basically you can call this as Os Filepath output. If you will run the program with some dummy arguments then that will also print as a program name.

The function that called with the varying number of arguments is known as variadic function. Or in other words, a user is allowed to pass zero or more arguments in the variadic function. fmt.Printf is the example of the variadic function, it required one fixed argument at the starting after that it can accept any number of arguments. 

Important Points :
 
 
* In the declaration of the variadic function, the type of the last parameter is preceded by an ellipsis, i.e, (…). It indicates that the function can be called at any number of parameters of this type. 

Syntax : 
function function_name(para1, para2...type)type{
// code...
}​
* Inside the function …type behaves like a slice. For example, suppose we have a function signature, i.e, add( b…int)int, now the a parameter of type[]int.
* You can also pass an existing slice in a variadic function. To do this, we pass a slice of the complete array to the function as shown in Example 2 below.
* When you do not pass any argument in the variadic function, then the slice inside the function is nil.
* The variadic functions are generally used for string formatting.
* You can also pass multiple slice in the variadic function.
* You can not use variadic parameter as a return value, but you can return it as a slice.

Example 1 :
// Go program to illustrate the
// concept of variadic function
package main

import(
	"fmt"
	"strings"
)

// Variadic function to join strings
func joinstr(element...string)string{
	return strings.Join(element, "-")
}

func main() {

// zero argument
fmt.Println(joinstr())
	
// multiple arguments
fmt.Println(joinstr("FREE", "LEARN"))
fmt.Println(joinstr("Free", "Time", "Learn"))
fmt.Println(joinstr("F", "R", "E", "E"))
	
}
​

Output : 

FREE-LEARN
Free-Time-Learn
F-R-E-E


Example 2 :

// Go program to illustrate the
// concept of variadic function
package main

import(
	"fmt"
	"strings"
)

// Variadic function to join strings
func joinstr(element...string)string{
	return strings.Join(element, "-")
}

func main() {
	
// pass a slice in variadic function
element:= []string{"free", "TIME", "learn"}
fmt.Println(joinstr(element...))
}​

Output : 

free-TIME-learn
In the Go programming language, the = is known as an assignment operator which is used to assign the value/expression to the left side variable/constant. While := is known as the short variable declaration which takes the following form,
variable_name := expression
The above statement assigns the value and determines the type of the expression. In such kind of declaration, there is no need to provide the type of the value/expression.
 
So, a short variable declaration (:=) required a value while declaring a new variable.
 
Consider the below example : demonstrating the difference between = and :=

Example 1 :
// Go program to demonstrate the
// difference between = and :=

package main

import (
	"fmt"
)

func main() {
	// Simple declaration & assignment
	var x int = 10

	// Shorthand declaration
	y := 20

	// Printing the values and types of both
	fmt.Printf("x = %T, %v\n", x, x)
	fmt.Printf("y = %T, %v\n", y, y)
}
Output :
x = int, 10
y = int, 20
 
See the output : the variable x is declared and assigned using the = operator and the variable y is declared and assigned using the := operator. In the first case, the var keyword and type are required while in the second case, the var keyword and type are not required.
 
Example 2 :
// Go program to demonstrate the
// difference between = and :=

package main

import (
	"fmt"
)

func main() {
	// Declare & assign using :=
	x, y, z := 10, 20, 30

	// Printing the types and values
	fmt.Printf("%T, %v\n", x, x)
	fmt.Printf("%T, %v\n", y, y)
	fmt.Printf("%T, %v\n", z, z)

	// Updating the values using =
	x, y, z = 100, 200, 300

	// Printing the types and values
	fmt.Printf("%T, %v\n", x, x)
	fmt.Printf("%T, %v\n", y, y)
	fmt.Printf("%T, %v\n", z, z)
}
Output :
int, 10
int, 20
int, 30
int, 100
int, 200
int, 300