C#
GO

C# to Go

10 lessons

Progress0%
1Introduction2Type System3Classes to Structs4Interfaces5Error Handling6Async to Goroutines7Generics8LINQ to Slices9Testing10Packages and Modules
All Mirror Courses
C#
GO
Classes to Structs
MirrorLesson 3 of 10
Lesson 3

Classes to Structs

Classes to Structs

Introduction

In this lesson, you'll learn about classes to structs in Go. Coming from C#, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
C#
From C#:

In C#, you're familiar with classes to structs.

GO
In Go:

Go has its own approach to classes to structs, which we'll explore step by step.

The Go Way

Let's see how Go handles this concept. Here's a typical example:

GO
Go Example
package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p Person) Greet() string {
    return fmt.Sprintf("Hi, I'm %s", p.Name)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p.Greet())
}

Comparing to C#

Here's how you might have written similar code in C#:

C#
C# (What you know)
class Person {
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age) {
        Name = name;
        Age = age;
    }

    public string Greet() =>
        $"Hi, I'm {Name}";
}

var p = new Person("Alice", 30);
Console.WriteLine(p.Greet());
Mirror Card
C#
From C#:

You may be used to different syntax or behavior.

GO
In Go:

Go has no class keyword — use struct for data and attach methods separately

Mirror Card
C#
From C#:

You may be used to different syntax or behavior.

GO
In Go:

Methods are defined outside the struct with a receiver: func (p Person) Method()

Mirror Card
C#
From C#:

You may be used to different syntax or behavior.

GO
In Go:

No constructors — use struct literal or a 'New' factory function by convention

Mirror Card
C#
From C#:

You may be used to different syntax or behavior.

GO
In Go:

No inheritance in Go — use embedding for composition

Mirror Card
C#
From C#:

You may be used to different syntax or behavior.

GO
In Go:

All fields in a struct are zero-initialized — no constructor required for defaults

Step-by-Step Breakdown

1. Struct Definition

Go structs define data fields. They look like C# auto-property classes but have no methods inside them.

C#
C#
class Rectangle {
    public double Width { get; set; }
    public double Height { get; set; }
}
GO
Go
type Rectangle struct {
    Width  float64
    Height float64
}

// Initialization
r1 := Rectangle{Width: 10, Height: 5}
r2 := Rectangle{10, 5}  // positional (avoid — fragile)
var r3 Rectangle        // zero value: {0, 0}

2. Methods with Receivers

Go methods are functions with a receiver — a named parameter that comes before the method name. The receiver can be a value or pointer.

C#
C#
class Rectangle {
    public double Area() => Width * Height;
    public void Scale(double factor) { Width *= factor; }
}
GO
Go
// Value receiver — does not modify original
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Pointer receiver — can modify original
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}
Rule of Thumb
Use pointer receivers (*T) when the method modifies the struct or when the struct is large. Use value receivers for small, immutable reads.

3. Factory Functions Instead of Constructors

Go has no constructors. Convention is to write a NewTypeName() function that returns an initialized struct or pointer.

C#
C#
public Person(string name, int age) {
    if (age < 0) throw new ArgumentException("age");
    Name = name; Age = age;
}
GO
Go
func NewPerson(name string, age int) (*Person, error) {
    if age < 0 {
        return nil, fmt.Errorf("age cannot be negative: %d", age)
    }
    return &Person{Name: name, Age: age}, nil
}

// Usage
p, err := NewPerson("Alice", 30)
if err != nil {
    log.Fatal(err)
}

4. Embedding Instead of Inheritance

Go has no inheritance. Use embedding to compose types — the embedded type's methods are promoted to the outer type.

C#
C#
class Employee : Person {
    public string Department { get; set; }
}
// Employee inherits Greet(), Name, Age
GO
Go
type Employee struct {
    Person           // embedded — promotes Name, Age, Greet()
    Department string
}

e := Employee{
    Person:     Person{Name: "Alice", Age: 30},
    Department: "Engineering",
}
fmt.Println(e.Greet())     // promoted from Person
fmt.Println(e.Name)        // promoted field
Common Pitfall
Embedding is not inheritance — there is no 'is-a' relationship. e is not a Person; it has a Person. You cannot pass Employee where Person is expected.

Common Mistakes

When coming from C#, developers often make these mistakes:

  • Go has no class keyword — use struct for data and attach methods separately
  • Methods are defined outside the struct with a receiver: func (p Person) Method()
  • No constructors — use struct literal or a 'New' factory function by convention
Common Pitfall
Don't assume Go works exactly like C#. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • No class — use struct for data, add methods with receivers separately
  • Pointer receivers (*T) for mutation; value receivers for reads
  • Use NewTypeName() factory functions instead of constructors
  • Embedding promotes fields/methods for composition — not inheritance
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your C# code in Go to practice these concepts.
PreviousNext