What a function is
A function is a named block of code that does one job. You write it once and run it whenever you need it. Splitting a program into functions keeps each piece small enough to read, test and change on its own.
Every Go function has a header and a body:
func functionName() {
// function body
}
funcis the keyword that starts a function declaration.functionNameis the name you will use to call it.- The parentheses hold the parameters. This function takes none, so they are empty.
- The curly braces wrap the body, the statements that run each time the function is called.
A function with nothing written after the parentheses returns no value. It just does its work, such as printing.
Defining is not calling
A declaration only tells Go that the function exists. Its body does not run until the function is called, which means writing its name followed by parentheses.
func sayHello() {
fmt.Println("Hello World")
}
func mainFunction() {
sayHello() // Hello World
sayHello() // Hello World
}
Each call runs the whole body from top to bottom, so two calls print the greeting twice. The parentheses matter: sayHello on its own is just the function as a value, and Go refuses to compile a statement that does nothing with it. In a test program I wrote, a bare sayHello line gave the error sayHello (value of type func()) is not used.
Order in the file doesn't matter either. Go lets a function call another one that is declared further down, because package-level declarations are all visible to each other. In a full program, the call has to start somewhere: execution begins in a function named main, and the lesson's mainFunction plays that role in the editor.
Capital letters decide who can use a name
Go has no public or private keywords. The first letter of a name does the job:
func SayHello() {} // exported (capital S): usable from other packages
func sayHello() {} // private to this package (lowercase s)
A name that starts with a capital letter is exported, so code in other packages can use it. A lowercase name is visible only inside its own package. The rule covers functions, types and struct fields alike.
That is why you write fmt.Println with a capital P: Println is exported from the fmt package. Writing fmt.println doesn't compile, because that name is not exported.
The exercise, step by step
The lesson asks for a function that greets everyone, then a call to it from mainFunction.
- Define
sayHelloabovemainFunction. Usefunc, the name, empty parentheses and a pair of braces. The reasoning is reuse: the greeting lives in its own block. - Print inside the braces.
fmt.Println("Hello everybody!")is the body. It runs only when the function is called. - Call it from
mainFunction. Without the call, defining the function changes nothing about what the program prints.
The finished code:
func sayHello() {
fmt.Println("Hello everybody!")
}
func mainFunction() {
sayHello()
}
Common mistakes
- Forgetting the parentheses on a call.
sayHellowithout()does not call anything. - Putting the opening brace on its own line. Go inserts a semicolon at the end of the header line, so
func sayHello()followed by a line holding only{fails withunexpected semicolon or newline before {. The brace goes on the header line. - Defining but never calling. A function nobody calls prints nothing.
- Lowercase
fmt.println. The printing function isPrintln. - Calling a function with the wrong capitalization. Names are case-sensitive, so
SayHelloandsayHelloare two different names.
Key takeaways
- A function is declared with
func, a name, parentheses and a brace-wrapped body. - The body runs once per call, and a call is the name followed by parentheses.
- Declaration order inside a package does not matter, but statements inside a body run top to bottom.
- Capitalized names are exported from their package, and lowercase names are private to it.