Background:
In Go, situations often arise where built-in types are insufficient, and it is necessary to define a custom data type with methods to encapsulate logic and extend functionality. This is achieved by creating custom types (type) and methods (func (r Receiver) MethodName()).
Problem:
Beginner developers often get confused — what is the difference between declaring a new type based on an existing one? How to correctly implement methods? How is the issue of copying, passing by value/pointer resolved? They make mistakes in visibility, receiver type, and working with embedded structs.
Solution:
To define a custom type, the keyword type is used. Methods are implemented using a receiver — this is important for working with interfaces.
Code example:
type MyInt int func (m MyInt) Double() int { return int(m) * 2 } // For structs: type User struct { Name string Age int } func (u *User) Birthday() { u.Age++ } var u = User{"Alice", 30} u.Birthday() // Age = 31
Key features:
Do custom types inherit methods from the base type?
No. If you define type MyInt int, then MyInt does not have the methods of int. For example, calling String() or other methods from the base type will not work.
Can methods be defined for type aliases?
For an alias (type MyType = ExistingType), methods cannot be added. Methods can only be defined for new types (type MyType ExistingType), not for aliases.
What receiver should be used: pointer or value?
If a method needs to modify the object, it is better to use a pointer. A value receiver copies the structure, which can lead to unexpected behavior if, for instance, the structure contains slice and map fields.
Code example:
type Counter struct { value int } func (c *Counter) Inc() { c.value++ } func main() { c := Counter{} c.Inc() // only with a pointer will the method change value }
A programmer created type MySlice []int and expected that methods of []int, for example, append, would work as methods on the type MySlice. It turned out that there were no methods, and accessing MySlice directly as []int was not allowed.
Pros:
Cons:
A type Counter int was defined with a method Inc, which allowed its use in several parts of the program with shared logic and without code duplication.
Pros:
Cons:
int.