Variables
In Go using the var
keyword we can declare a list of variables of same type.
var a, b, c int
Variables are mutable types. Go does not support immutable types. (Go does have constants but they are not the same as immutable types). We can also define variables in the global scope. Once a variable is defined it can be used in its scope.
Scope is where a particular variable is valid. We will dive much deeper into scope in a later chapter.
If we do also declare the variable the same time we define it. We can also declare a variable without defining its type. For simple types
var a = 10
var b int32 = 26
As we can see we can create variables with type declared and not declared. When we don’t declare type, the type is inferred. Type inference always chooses the default type for value. For example
var a = 10 // int
var b = 1.5 // float64
We can also use short variable declaration.
short := 10
One thing to note though, short variable declaration can not be used in global scope.
Naming Variables
- Has to start with Alphabets or _
count or _data or _1
- Should be Camel Case
userID
- Short names preferred over long
This Talk from 2014 sums it up nicely.
Shadowing
Any variable defined in an outer scope can be shadowed by a new variable in inner scope. When shadowing we can also change type of variable.
Function
We already saw some examples of functions. Our func main
was a function. It is a special type of function. There is another special type of function. It is the init
function.
init
init
function gets executed before anything else in the package. We can also have more than 1 init
function per package. All the init
functions will execute before anything else in the package. If we have init
function in multiple files in the same package, init
function is executed in lexical file order.
For example in our git repository
change directory into functions
folder.
We have 3 files in there. a.go
, b.go
and main.go
we have a total of 5 init
functions. 3 in main.go
and 1 each on a.go
and b.go
.
cd function
go run *
We would see
init from file a
init from file b
hello from init 1
hello from init 2
hello from init 3
Hello World
This information should not be something we rely on while building application. This would be a terrible practice to build software on such assumption.
main
main
is the entry point to our application. After all init
steps has finished execution of main
begins. We can have only one main
function per application. And main
package can not be exported or imported by other.
Other than main
and init
users have free reign to define
any functions in go.
Anatomy of functions
func <funcname> (0 or more parameters)(0 or more return types) {
}
Function has a name. It can take 0 or more parameters and it can return 0 or more things from a function.
For example:
func Greet() {
fmt.Println("hello")
}
func Add(a, b int) int {
return a + b
}
func Divide(a, b int) (int, int) {
return a / b, a % b
}
Named returns
We can also have named return. Named returns can be useful when we have multiple returns and its not immediately clear what the values represent when returned.
func NamedDivide(a, b int) (quotient int, remainder int) {
quotient, remainder = a/b, a%b
return
}
In the previous Divide
function. We had to look at the code to figure out that the first response was the quotient and the second was the remainder. In this example the function definition makes it super clear. We probably won’t even need any more documentation.
Naming functions
Same rules as variable naming apply.
Functions are values
Functions are first class citizens in Go. That means we can create variables that are of type function. As well as pass functions as function parameters and receive function from function return.
func TakeFunc(take func() string) {
data := take()
fmt.Println(data)
}
func GiveFunc() func() string {
f := func() string {
return "give"
}
return f
}
Overloading
Go does not support function overloading. That means we can not have two function that has the same name but different signature. But we can always shadow a function in inner scope.
For example we can define a new function in main
called Greet
. Now when we use Greet()
we are using the inner function.
Greet := func() string {
return "shadow outer Greet"
}
Next Steps
This is Part 3 of this Go crash course series.