Go Tutorial for C# Developers: Understanding this vs Method Receivers

When moving between C# and Go (Golang), one of the most noticeable differences is how each language defines methods on types. At first glance, the syntax looks different, but the underlying concept is surprisingly similar.
Defining Methods in C#
🔗In C#, methods are defined inside classes. The this
keyword refers to the current instance of the class. Instance methods automatically have access to the instance’s fields and properties.
Example: C# UserService
csharppublic class UserService
{
public string ServiceName { get; set; }
public UserService(string name)
{
ServiceName = name;
}
// Instance method
public void RegisterUser(string user)
{
Console.WriteLine($"{user} registered with {this.ServiceName}");
}
}
// Usage
var service = new UserService("Main Service");
service.RegisterUser("Alice");
👉 Here, this.ServiceName
makes it explicit that ServiceName
belongs to the current object instance.
Defining Methods in Go
🔗In Go, there are no classes. Instead, you use structs to group fields and receiver functions to attach behavior. A receiver is like this
in C#, but declared explicitly. Receivers can be either value receivers (u UserService
) or pointer receivers (u *UserService
). Pointer receivers are common because they allow modifying the struct.
Example: Go UserService
gopackage main
import "fmt"
type UserService struct {
ServiceName string
}
// Method with pointer receiver
func (s *UserService) RegisterUser(user string) {
fmt.Printf("%s registered with %s\n", user, s.ServiceName)
}
func main() {
service := UserService{ServiceName: "Main Service"}
service.RegisterUser("Alice")
}
👉 Notice how (s *UserService)
works like this
in C#:
s
represents the instance.- You access fields with
s.ServiceName
. - The call
service.RegisterUser("Alice")
looks almost identical to C#.
💡 In Go, it’s common practice to name the receiver with a short, usually one-letter identifier (often the first letter of the type, like u
for UserService
), unlike C# where this
is fixed.
Syntax Comparison
🔗Concept | C# | Go |
---|---|---|
Type definition | class UserService { ... } | type UserService struct { ... } |
Instance reference | this | Explicit receiver (s *UserService) |
Method definition | Inside the class | Outside the struct, attached via func |
Method call | service.RegisterUser(user) | service.RegisterUser(user) |
Key Differences
🔗-
Location of methods
- C#: Defined inside the class.
- Go: Defined outside the struct, attached by declaring a receiver.
-
Receiver vs this
- C#:
this
is implicit (you don’t declare it). - Go: Receiver is explicit (you choose the name:
s
,u
, etc.).
- C#:
-
Inheritance vs Composition
- C#: Classes support inheritance and polymorphism.
- Go: No inheritance — encourages composition and interfaces instead.
-
Pointers in Go
- Go requires you to decide: value receiver vs pointer receiver.
- C# hides this — instance methods always work on references (except for struct types in C#).
Mental Model
🔗You can think of Go’s receiver as C#’s this
made explicit:
In C#:
csharpthis.RegisterUser(user);
In Go:
gos.RegisterUser(user) // where 's' is explicitly declared in the method signature
Both produce the same usage style:
csharpservice.RegisterUser("Alice"); // C#
goservice.RegisterUser("Alice") // Go
Takeaway
🔗- C#: Object-oriented, methods live inside classes,
this
is implicit. - Go: Struct-based, methods are functions with explicit receivers.
Despite the syntax differences, when you write:
csharpservice.RegisterUser(user); // C#
goservice.RegisterUser(user); // Go
…the calling code looks nearly identical. The difference lies in where the method is attached and how the instance reference is handled.

Alvin
Software engineer, interested in financial knowledge, health concepts, psychology, independent travel, and system design.