Go Series: Function Declarations
Tags: go, beginners
Published: 2022-10-29 08:29:10

![Golang Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tdkgcszo71tdh7eans9.png)

{% replit @achristoph/Functions  %}


## Declaring functions
There are a few ways of declaring functions in Go.

The most basic function has no argument and no return value. The main function in go is this type of function
```go
func Say() {
  fmt.Println("Hi")
}
```
Function can have a return value. In Go, not only the type that is declared, we can also declare the variable that is used as the return value. This helps to make the function more descriptive and self-documented - we can tell what is being return just by reading the function declaration.
```go
func LastName() (name string) {
  name = "Smith"
  return name
}
```
In comparison of the standard declaration:
```go
func LastName() string {
  var name string
  name = "Smith"
  return name
}

```
One note however, by declaring `(name string)` as above , the unused variable checking is no longer using used whereas if `var name string` is not used, go will not compile. The same rule applies to parameter as well - unused parameters will not trigger the unused variable checking.
Below is an example of a function with parameters and named return value declaration
```go
func FullName(first string, last string) (fullName string) {
	fullName = first + " " + last
	f := first + " " + last
	return f
}
```

We can shorten the parameter declaration by grouping same type parameters. Make sure that the method still looks readable, the grouped parameters can be less readable the definition as we need to scan more to the end to see the type.
```go
func FullNameWithMiddle(first, middle, last string, id int) (fullName string) {
	fullName = first + " " + last
	return fullName
}
```

Function can return multiple values, a common pattern in go is returning an error as the last return value and this allow us to check if the function has error or not. More into error handling later in the series
```go
func FullNameWithValidation(first string, last string) (fullName string, err error) {
	if len(first) == 0 {
		return fullName, errors.New("First Name cannot be empty")
	}
	fullName = first + " " + last
	return fullName, err
}
```

If the function has named return values, it is possible to have a return without specifying them. However, this is not recommended since it makes it harder to read as you'll need to scan all the way up to see what they are.

```go
func MagicNumber(num int) (n int, err error) {
	if num == 0 {
		// this still returns n and err, but not obviously visible without going back to function definition line, it may look like it's returning nothing
		return
	}
	if num > 100 {
		return n, errors.New("larger than 100 is not valid")
	}
	fmt.Println("n is not calculated if an error occurred")
	n = num * 100

	return n, err
}
```

Named parameter features in popular language such as typescript, python, ruby. While it might be surprising, go uses its struct to simulate the feature. While it might look more verbose, it forces a clear documentation of what is being passed into the function

```go
type MyOpts struct {
	FirstName string
	LastName  string
	Age       int
}
func MyFnWithNamedParams(opts MyOpts) {}
```
Another common feature is variadic parameter. Go does have this feature. Note the variadic parameter needs to be the last parameter in the function.
```go
func MyNumbers(nums ...int) {}
MyNumbers(1, 2, 3)
```

Function can also have another function passed into the function. We'll look more into detail in function patterns topic.
 
```go
func FnWithLogger(fn func(int, int) int) int {	
  num1 := 1
  num2 := 2
  result := fn(num1, num2)
  fmt.Println("logging", result)
  return result
}
```

This concludes the introduction of function in Go. Next a few topics, we'll dive into defer and closure in go.