Golang Tutorial
Fundamentals
Control Statements
Functions & Methods
Structure
Arrays & Slices
String
Pointers
Interfaces
Concurrency
Promoted methods in Go is an extension of the concept of promoted fields, which we covered in the previous tutorial. Just as fields from an embedded struct can be accessed directly from the outer struct, methods defined on an embedded struct are automatically available (or "promoted") to the outer struct.
Here's a tutorial on promoted methods in Go:
When a struct embeds another struct, the methods defined on the embedded struct are directly accessible from the outer struct.
package main import "fmt" type Writer struct{} func (w Writer) Write() { fmt.Println("Writing...") } type Author struct { Writer } func main() { a := Author{} a.Write() // Calling the Write method which is promoted from the Writer struct }
You can override a promoted method by defining a method with the same name in the outer struct:
func (a Author) Write() { fmt.Println("Author is writing...") } func main() { a := Author{} a.Write() // This now prints "Author is writing..." }
If you override a method, the original method from the embedded struct is shadowed, but it's still accessible using the embedded struct's type:
a.Writer.Write() // This will call the Write method of the Writer struct and print "Writing..."
Promoted methods also count when determining if a struct implements an interface:
type Writer interface { Write() } type Pen struct{} func (p Pen) Write() { fmt.Println("Pen is writing...") } type FancyPen struct { Pen } func main() { var w Writer = FancyPen{} w.Write() // This prints "Pen is writing..." }
In the above example, FancyPen
implements the Writer
interface because it has a promoted Write
method from the embedded Pen
struct.
If a struct embeds multiple structs, and more than one of those structs have methods with the same name, then the outer struct can't access those methods directly due to ambiguity:
type Reader struct{} func (r Reader) Read() { fmt.Println("Reading...") } type Writer struct{} func (w Writer) Read() { fmt.Println("Writing and reading...") } type Author struct { Reader Writer } func main() { a := Author{} // a.Read() // This would result in a compilation error due to ambiguity a.Reader.Read() // This is okay, prints "Reading..." a.Writer.Read() // This is okay, prints "Writing and reading..." }
Promoted methods offer a way to reuse behavior and logic across structs, allowing for cleaner and more maintainable code. However, care should be taken to avoid ambiguous situations and ensure the design remains intuitive.
Defining and using methods in Golang structures:
In Go, methods are functions associated with a type. You can define methods for your custom structures to perform operations specific to that type.
package main import "fmt" type Rectangle struct { Width float64 Height float64 } // Method for calculating the area of a rectangle func (r Rectangle) Area() float64 { return r.Width * r.Height } func main() { rect := Rectangle{Width: 5, Height: 10} fmt.Println("Area:", rect.Area()) }
Pointer receivers vs value receivers in Golang methods:
You can define methods with either pointer receivers or value receivers. Pointer receivers allow you to modify the original instance.
// Using value receiver func (r Rectangle) DoubleArea() float64 { return 2 * r.Area() } // Using pointer receiver func (r *Rectangle) Scale(factor float64) { r.Width *= factor r.Height *= factor }
Working with methods and interfaces in Golang structs:
Interfaces in Go allow you to define a set of methods that a type must implement. This enables polymorphism.
type Shape interface { Area() float64 } func GetArea(s Shape) float64 { return s.Area() } // Rectangle now implements the Shape interface func (r Rectangle) Area() float64 { return r.Width * r.Height }
Composition and method embedding in Golang structs:
Go supports composition by embedding one struct within another. Methods of the inner struct become part of the outer struct.
type Car struct { Model string } type Engine struct { Horsepower int } type SportsCar struct { Car Engine }
Accessing fields and methods in embedded structs in Golang:
You can access fields and methods of embedded structs directly on the outer struct.
sc := SportsCar{Car{"Tesla"}, Engine{500}} fmt.Println(sc.Model) // Accessing Car's field fmt.Println(sc.Horsepower) // Accessing Engine's field
Anonymous fields and method access in Golang structs:
Fields or methods of an embedded struct can be promoted to the outer struct, making them accessible directly.
type SportsCar struct { Car Engine // No need to explicitly declare Car and Engine here } sc := SportsCar{Car{"Tesla"}, Engine{500}} fmt.Println(sc.Model) // Accessing Car's field directly fmt.Println(sc.Area()) // Accessing Car's method directly
Method visibility and naming conventions in Golang structs:
Capitalized method names are exported and accessible outside the package, while lowercase names are not.
type MyStruct struct { } // Exported method func (m *MyStruct) ExportedMethod() {} // Unexported method func (m *MyStruct) unexportedMethod() {}
Golang struct methods vs standalone functions:
Methods are associated with a type, while standalone functions operate on independent data.
// Standalone function func CalculateArea(width, height float64) float64 { return width * height } // Method func (r Rectangle) Area() float64 { return r.Width * r.Height }
You can choose between methods and standalone functions based on whether the operation is more closely tied to a specific type or not.