Question
In Go, I found function declarations like these:
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// ...
}
func (s *GracefulServer) BlockingClose() bool {
// ...
}
What do the parts in parentheses before the function name mean, such as (h handler) and (s *GracefulServer)?
What does the full declaration mean when those parts are included?
The main point of confusion is not the difference between functions and methods in general, but specifically the meaning of the syntax that appears before the function name.
Short Answer
By the end of this page, you will understand that the extra parentheses before a Go function name define a receiver, which makes the function a method attached to a type. You will learn how value receivers and pointer receivers work, how to read declarations like func (s *Server) Start(), and when each style is used in real Go code.
Concept
In Go, a declaration like this:
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// ...
}
is not an ordinary function. It is a method.
The part before the method name:
(h handler)
is called the receiver.
A receiver says:
- this method belongs to the type
handler - inside the method, that value will be available through the name
h
So this method can be read as:
ServeHTTPis a method on the typehandler- when called, the current
handlervalue is referred to ash
Similarly:
func (s *GracefulServer) BlockingClose() bool {
// ...
}
means:
Mental Model
Think of a Go type as a tool, and a method as an action that tool knows how to perform.
- the type is the object
- the receiver is the label for "this object"
- the method is the action attached to it
For example, imagine a Car type.
func (c Car) Drive() {
// ...
}
You can read this as:
- "A
Carhas aDrivebehavior" - inside the method,
cmeans "this car"
So the receiver is similar to saying this instance.
If you have seen other languages, it is a bit like:
thisin Java or C#selfin Python
Go just writes it explicitly in the method declaration:
func (c Car) Drive()
instead of hiding it behind a keyword.
A pointer receiver is like saying:
- "work with the real car itself"
A value receiver is like saying:
Syntax and Examples
Basic syntax
Regular function
func add(a int, b int) int {
return a + b
}
This is a normal function. It is not attached to any type.
Method with a value receiver
type Counter struct {
Value int
}
func (c Counter) Display() int {
return c.Value
}
Display is a method on Counter.
- receiver name:
c - receiver type:
Counter
Call it like this:
counter := Counter{Value: 5}
fmt.Println(counter.Display())
Method with a pointer receiver
type Counter {
Value
}
Increment() {
c.Value++
}
Step by Step Execution
Consider this example:
package main
import "fmt"
type Counter struct {
Value int
}
func (c *Counter) Increment() {
c.Value++
}
func main() {
counter := Counter{Value: 10}
counter.Increment()
fmt.Println(counter.Value)
}
Step by step
1. Define a type
type Counter struct {
Value int
}
This creates a struct type named Counter.
2. Define a method on that type
func (c *Counter) Increment() {
c.Value++
}
This says:
Incrementis a method on*Countercpoints to theCountervalue that called the method
Real World Use Cases
Methods with receivers are used throughout Go code.
HTTP handlers
A common real example is:
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// handle request
}
This lets a type satisfy the http.Handler interface.
Use case:
- web servers
- middleware
- API routing
State-changing services
func (s *Server) Shutdown() error {
// update internal state
return nil
}
Pointer receivers are common for:
- servers
- database clients
- caches
- job queues
Domain models
func (u User) FullName() string {
return u.FirstName + " " + u.LastName
}
Value receivers are often used for read-only behavior:
Real Codebase Usage
In real Go projects, receiver methods are used to organize behavior around types.
Common patterns
1. Guard clauses in methods
func (s *Server) Start() error {
if s == nil {
return fmt.Errorf("server is nil")
}
if s.running {
return nil
}
s.running = true
return nil
}
This is common when a method depends on internal state.
2. Validation methods
func (c Config) Validate() error {
if c.Port <= 0 {
return fmt.Errorf("invalid port")
}
return nil
}
This keeps validation logic close to the data it validates.
3. Mutating methods use pointer receivers
func (u *User) SetEmail(email string) {
u.Email = email
}
Common Mistakes
1. Thinking the receiver is just a normal parameter
This is a very common first impression.
Broken mental model:
func (c Counter) Show()
This is not a function with a strange parameter before the name. It is a method declaration.
Remember:
- receiver syntax makes it a method
- methods are called with dot syntax
counter.Show()
2. Using a value receiver when you need to modify the original
Broken example:
type Counter struct {
Value int
}
func (c Counter) Increment() {
c.Value++
}
This only modifies a copy.
Fix:
func (c *Counter) Increment() {
c.Value++
}
3. Mixing pointer and value receivers carelessly
Broken style:
func Name() { u.name }
SetName(name ) { u.name = name }
Comparisons
Function vs method
| Feature | Function | Method |
|---|---|---|
| Attached to a type | No | Yes |
| Has receiver | No | Yes |
| Call style | add(1, 2) | counter.Increment() |
| Organizes behavior around data | Less directly | Yes |
Function example
func add(a int, b int) int {
return a + b
}
Method example
func Increment() {
c.Value++
}
Cheat Sheet
Receiver syntax
func (name Type) MethodName(params) returnType {
// ...
}
Examples
Value receiver
func (u User) FullName() string {
return u.FirstName + " " + u.LastName
}
Pointer receiver
func (u *User) SetName(name string) {
u.Name = name
}
How to read it
func (s *Server) Start() error
Read as:
Startis a method- receiver variable:
s - receiver type:
*Server - return type:
error
Rules of thumb
FAQ
What is the thing in parentheses before a function name in Go?
It is the receiver. It makes the declaration a method attached to a type.
Is (h handler) a function parameter?
No. It is not a regular parameter. It is receiver syntax used for methods.
What does *GracefulServer mean in the receiver?
It means the method has a pointer receiver, so it works with a pointer to GracefulServer and can modify the original value.
What is the difference between (c Counter) and (c *Counter)?
(c Counter) gets a copy of the value. (c *Counter) gets a pointer to the original value.
When should I use a pointer receiver in Go?
Use one when the method changes the struct, when the struct is large, or when you want consistent behavior across methods.
Are methods just functions in Go?
A method is a special kind of function that is attached to a type through a receiver.
Why does ServeHTTP often use a receiver?
Because Go's HTTP system uses interfaces, and a type can satisfy http.Handler by implementing the ServeHTTP method.
Mini Project
Description
Build a small Go program with a BankAccount type to practice method receivers. This project shows the difference between read-only methods and state-changing methods, which is exactly the reason Go uses value and pointer receivers.
Goal
Create a BankAccount type with methods to read the balance and deposit money using the correct receiver types.
Requirements
- Define a
BankAccountstruct with an owner name and balance. - Add a method that returns a formatted account summary.
- Add a method that deposits money into the account.
- Use a pointer receiver for the method that changes the balance.
- Create an account in
mainand show the balance before and after a deposit.
Keep learning
Related questions
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Concatenating Slices in Go with append
Learn how to concatenate two slices in Go using append and the ... operator, with examples, pitfalls, and practical usage.
Convert String to Integer in Go: Idiomatic Parsing with strconv.Atoi
Learn the idiomatic way to convert a string to an int in Go using strconv.Atoi, with examples, errors, and common mistakes.