Go language interfaces
below:
Go's interface design is simple yet powerful, and is an important tool for achieving polymorphism and decoupling.
Interfaces allow us to bind different types to a set of common methods, thereby enabling polymorphism and flexible design.
Interface Features
Implicit implementation:
- Go has no keyword to explicitly declare that a type implements an interface.
- As long as a type implements all the methods required by an interface, the type is automatically considered to implement that interface.
Interface type variables:
- An interface variable can store any value that implements the interface.
- An interface variable actually consists of two parts:
- Dynamic type: stores the actual value type.
- Dynamic value: stores the concrete value.
Zero value interface:
- The zero value of an interface is
nil。 - The value of an uninitialized interface variable is
nil, and it does not contain any dynamic type or value.
Empty interface:
- Defined as
interface{}, can represent any type.
Common uses of interfaces
- PolymorphismDifferent types implementing the same interface achieve polymorphic behavior.
- DecouplingDefining dependencies through interfaces reduces coupling between modules.
- Generalization: Using the empty interface
interface{}represents any type.
Interface definition and implementation
Interface definitions use the keywordinterface, which contains method declarations.
Example
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/* Define struct */
type struct_name struct {
/* variables */
}
/* Implement interface methods */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* Method implementation */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/* Method implementation*/
}
Define a simple interface:
type Shape interface {
Area() float64
Perimeter() float64
}Shapeis an interface that defines two methods:AreaandPerimeter。- Any type that implements these two methods is considered to have implemented the interface.
ShapeInterface.
Implement interface:Types implement an interface by implementing all the methods required by the interface.
Example
import (
"fmt"
"math"
)
// Define interface
type Shape interface {
Area() float64
Perimeter() float64
}
// Define a struct
type Circle struct {
Radius float64
}
// Circle implements Shape interface
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
func main() {
c := Circle{Radius: 5}
var s Shape = c // Interface variables can store types that implement the interface
fmt.Println("Area:", s.Area())
fmt.Println("Perimeter:", s.Perimeter())
}
Execute the above code, the output is:
Area: 78.53981633974483 Perimeter: 31.41592653589793
Empty interface
Empty interfaceinterface{}It is a special interface in Go, representing the superset of all types.
- Any type implements the empty interface.
- It is often used in scenarios that need to store data of any type, such as generic containers, generic parameters, etc.
Example
import "fmt"
func printValue(val interface{}) {
fmt.Printf("Value: %v, Type: %T\n", val, val)
}
func main() {
printValue(42) // int
printValue("hello") // string
printValue(3.14) // float64
printValue([]int{1, 2}) // slice
}
Execute the above code, the output is:
Value: 42, Type: int Value: hello, Type: string Value: 3.14, Type: float64 Value: [1 2], Type: []int
Type assertion
Type assertion is used to extract the underlying value from an interface type.
Basic syntax:
value := iface.(Type)
ifaceis an interface variable.Typeis the concrete type to be asserted.- If the type does not match, it triggers
panic。
Example
import "fmt"
func main() {
var i interface{} = "hello"
str := i.(string) // Type assertion
fmt.Println(str) // Output: hello
}
type assertion with a check
To avoid panic, a checked type assertion can be used:
value, ok := iface.(Type)
okIt is a boolean value indicating whether the assertion was successful.- If the assertion fails,
valueis the zero value,okisfalse。
Example
import "fmt"
func main() {
var i interface{} = 42
if str, ok := i.(string); ok {
fmt.Println("String:", str)
} else {
fmt.Println("Not a string")
}
}
Execute the above code, the output is:
Not a string
type switch
Type switch is a syntax construct in Go used to execute different logic based on the concrete type of an interface variable.
Example
import "fmt"
func printType(val interface{}) {
switch v := val.(type) {
case int:
fmt.Println("Integer:", v)
case string:
fmt.Println("String:", v)
case float64:
fmt.Println("Float:", v)
default:
fmt.Println("Unknown type")
}
}
func main() {
printType(42)
printType("hello")
printType(3.14)
printType([]int{1, 2, 3})
}
Execute the above code, the output is:
Integer: 42 String: hello Float: 3.14 Unknown type
Interface composition
Interfaces can describe more complex behaviors through nesting and composition.
Example
import "fmt"
type Reader interface {
Read() string
}
type Writer interface {
Write(data string)
}
type ReadWriter interface {
Reader
Writer
}
type File struct{}
func (f File) Read() string {
return "Reading data"
}
func (f File) Write(data string) {
fmt.Println("Writing data:", data)
}
func main() {
var rw ReadWriter = File{}
fmt.Println(rw.Read())
rw.Write("Hello, Go!")
}
dynamic value and dynamic type
An interface variable actually contains two parts:
- Dynamic type: the concrete type stored in the interface variable.
- Dynamic value: the value of the concrete type.
Example of dynamic value and dynamic type:
Example
import "fmt"
func main() {
var i interface{} = 42
fmt.Printf("Dynamic type: %T, Dynamic value: %v\n", i, i)
}
Execute the above code, the output is:
Dynamic type: int, Dynamic value: 42
Zero value of interface
The zero value of an interface is nil.
When both the dynamic type and dynamic value of an interface variable are nil, the interface variable is nil.
Interface zero value example:
Example
import "fmt"
func main() {
var i interface{}
fmt.Println(i == nil) // Output: true
}
Practice examples
The following two examples demonstrate the use of interfaces:
Example 1
import (
"fmt"
)
type Phone interface {
call()
}
type NokiaPhone struct {
}
func (nokiaPhone NokiaPhone) call() {
fmt.Println("I am Nokia, I can call you!")
}
type IPhone struct {
}
func (iPhone IPhone) call() {
fmt.Println("I am iPhone, I can call you!")
}
func main() {
var phone Phone
phone = new(NokiaPhone)
phone.call()
phone = new(IPhone)
phone.call()
}
In the above example, we defined an interface.Phone, the interface contains a methodcall(). Then wemainIn the function, aPhonetype variable is defined, and values are assigned to it respectively asNokiaPhoneandIPhone. Then callcall()method, the output is as follows:
I am Nokia, I can call you! I am iPhone, I can call you!
The second interface example:
Example
import "fmt"
type Shape interface {
area() float64
}
type Rectangle struct {
width float64
height float64
}
func (r Rectangle) area() float64 {
return r.width * r.height
}
type Circle struct {
radius float64
}
func (c Circle) area() float64 {
return 3.14 * c.radius * c.radius
}
func main() {
var s Shape
s = Rectangle{width: 10, height: 5}
fmt.Printf("Rectangle area: %f\n", s.area())
s = Circle{radius: 3}
fmt.Printf("Circle area: %f\n", s.area())
}
In the above example, we defined a Shape interface, which defines a method area() that returns an area value of type float64. Then, we defined two structs, Rectangle and Circle, which respectively implement the area() method of the Shape interface. In the main() function, we first defined a variable s of type Shape, then assigned instances of Rectangle and Circle to it respectively, and via the area() method calculated their areas and printed them out. The output is as follows:
矩形面积: 50.000000 圆形面积: 28.260000
It should be noted that an interface type variable can store a value of any type that implements the interface. In the example, we assigned instances of both Rectangle and Circle types to the variable s of type Shape, and called their area calculation methods via the area() method.
other extensions