Anonymous Functions
In Go, anonymous functions are functions defined without a name. They are often used as inline functions, assigned to variables, or passed as arguments to other functions. Anonymous functions are useful when you need a quick, short-lived function without the need to define it separately.
Syntax
An anonymous function is defined using the func
keyword, followed by its parameters and body, without a name:
func(parameter_list) return_type {
// function body
}
Example Usage
-
Assigning to a Variable:
add := func(a int, b int) int {
return a + b
}
fmt.Println(add(3, 4)) // Output: 7 -
Inline Execution:
result := func(a, b int) int {
return a * b
}(3, 5)
fmt.Println(result) // Output: 15 -
Passing as an Argument:
func apply(f func(int) int, value int) int {
return f(value)
}
square := func(x int) int { return x * x }
fmt.Println(apply(square, 4)) // Output: 16
Characteristics
- No Name: They are defined without a function name.
- Closures: Anonymous functions can capture and use variables from their surrounding scope, making them closures.
- Short-Lived: Typically used for small, localized tasks.
Common Use Cases
- Callback functions.
- Short-lived logic within higher-order functions like
sort.Slice
. - Defining behavior inline without polluting the global namespace.
Sample Service
let's define a NotificationService
that sends a notification to a user via Email and SMS:
// EmailProvider defines the interface for sending emails.
type EmailProvider interface {
SendEmail(to string, subject string, body string) error
}
// SmsProvider defines the interface for sending SMS messages.
type SmsProvider interface {
SendSms(to string, message string) error
}
// NotificationService defines the interface for notifying users.
type NotificationService interface {
NotifyUser(email string, phone string, message string) error
}
note that NotificationService
logically depends on EmailProvider
and SmsProvider
type smtpEmailProvider struct {
host string
port int
username string
password string
}
func (m *smtpEmailProvider) connect() (SMTPConnection, error) {
// connect to SMTP server
}
func (m *smtpEmailProvider) send(conn SMTPConnection, to string, subject string, body string) error {
// send an email via SMTP server connection
conn.Send(to, subject, body)
}
func (m *smtpEmailProvider) SendEmail(to string, subject string, body string) error {
// connect to SMTP server
conn, err := m.connect(m.host, m.port, m.username, m.password)
err = m.send(conn, to, subject, body)
return err
}
type smsGatewayProvider struct {
apiUrl string
apiKey string
}
func (m *smsGatewayProvider) SendSms(to string, message string) error {
someSmsSender.Send(m.apiUrl, m.apiKey, to, message)
return err
}
type userNotifier struct {
emailProvider EmailProvider
smsProvider SmsProvider
}
func (un *userNotifier) NotifyUser(email string, phone string, message string) error {
err := un.emailProvider.SendEmail(email, "Notification", message)
err = un.smsProvider.SendSms(phone, message)
return err
}
Register Services via anonymous funcs (RegisterFunc)
registering EmailProvider
service:
ore.RegisterFunc[EmailProvider](ore.Scoped, func(ctx context.Context) (EmailProvider, error) {
return &smtpEmailProvider{
host: "smtp.gmail.com",
port: 587,
username: "someemailaddress@gmail.com",
password: "somepasswordhere",
}, ctx
})
registering SmsProvider
service:
ore.RegisterFunc[SmsProvider](ore.Scoped, func(ctx context.Context) (SmsProvider, error) {
return &smsGatewayProvider{
apiUrl: "https://gateway.somesmsprovider.com",
apiKey: "1f7b3bb5-ce07-4119-864d-0995f6f89515",
}, ctx
})
registering NotificationService
service:
ore.RegisterFunc[NotificationService](ore.Scoped, func(ctx context.Context) (NotificationService, error) {
emailProviderService, ctx := ore.Get[EmailProvider](ctx)
smsProviderService, ctx := ore.Get[SmsProvider](ctx)
return &userNotifier{
emailProvider: emailProviderService,
smsProvider: smsProviderService,
}, ctx
})
Note that the scope (ctx
) is well passed through all dependencies of the NotificationService
chain; This is very
crucial for the scoped services to be resolved correctly.