面向对象编程 OOP
面向对象编程(OOP)是许多编程语言中的常见模式。面向对象的编程具有许多优点,例如可重用性,多态性和封装性。Go可以使用不同的方法来实现OOP的概念。 Go中支持OOP中的类,接口和方法,但是没有类型继承结构。
在Golang官方文档的“常见问题解答”中,有一个有趣的问题:“Go是一种面向对象的语言吗?”
指针
指针是Go中支持的寻址机制。 指针有两个运算符称为寻址(&)和取指针所指向的变量的值(*)。
package main
import (
"fmt"
)
func main() {
a := 42
//prints out the value of a
fmt.Println("value of a: ", a)
//prints out the memory address that pointing to "a" variable
fmt.Println("memory address of a: ", &a)
}
// output
// value of a: 42
// memory address of a: 0xc000014080
使用指针,变量可以寻址到另一个变量。 例如,b变量可以寻址到另一个变量(在此代码中,该变量称为a)。
package main
import (
"fmt"
)
func main() {
a := 42
//prints out the value of a
fmt.Println("value of a: ", a)
//prints out the memory address that pointing to "a" variable
fmt.Println("memory address of a: ", &a)
b := &a
//prints out the memory address of "b" variable
fmt.Println("value of b:", b)
//to prints out the value of b, use * (dereference) operator
fmt.Println("value of b using * operator: ", *b)
}
// output
// value of a: 42
// memory address of a: 0xc000014080
// value of b: 0xc000014080
// value of b using * operator: 42
如果a的值更改,则*b的值也会更改。
//changes the value of "a"
a = 45
fmt.Println("value of a: ", a)
fmt.Println("value of *b: ", *b)
// output
// value of a: 45
// value of *b: 45
struct
类是OOP的重要组成部分。 在Go中,有一个类似的概念称为struct。
// struct 声明
type structName struct {
//field name type
member int
member2 string
member3 []string
}
struct的使用示例。 说明了一个有说话能力的人。
//declare a struct called person
type person struct {
name string
age int
}
//declare a method say() with type person as receiver
func (p person) say() {
fmt.Println("Hello, my name is: ", p.name)
}
将已定义的struct分配给变量才能使用,如下所示:
package main
import "fmt"
//declare a struct called person
type person struct {
name string
age int
}
//declare a method say() with type person as receiver
func (p person) say() {
fmt.Println("Hello, my name is: ", p.name)
}
func main() {
//实例化person,并赋值
p1 := person{name: "Enki Gilbert", age: 42}
//call a method say()
p1.say()
}
// output
// Hello, my name is: Enki Gilbert
Go中还提供了匿名struct。
s1 := struct{
//declare some fields
field1 int
field2 []string
}{
//instantiate directly
field1: 12,
field2: []string{"hi","mate"},
}
Composition
Go不支持继承,我们可以改用struct组合。
package main
import (
"fmt"
)
//declare a struct called person
type person struct {
name string
age int
}
//composition example
//declare a struct called manager that includes another struct called person
type manager struct {
person
team string
}
//declare a method say() with type person as receiver
func (p person) say() {
fmt.Println("Hello, my name is: ", p.name)
}
func main() {
//instantiate the person
p1 := person{"Enki Gilbert", 42}
//instantiate the manager and assign person field by using p1 variable
m1 := manager{person: p1, team: "Racing Team Solvalou"}
//the say() method is still available
m1.say()
}
// output
// Hello, my name is: Enki Gilbert
我们声明一个struct称为manager,person嵌入manager。say()方法仍可用于manager,因为它构成了另一个具有say()方法的struct。
实例化具有嵌套的struct的替代语法:
//instatiate the person struct into person field directly
m1 := manager{person: person{"Enki Gilbert", 42}, team: "Racing Team Solvalou"}
Interface
Interface是编程中的另一个强大概念。 Interface与struct类似,但只包含一些抽象方法。 在Go中,Interface定义了通用行为的抽象。
package main
import (
"fmt"
)
//declare a rectangle struct
type rectangle struct {
length int
width int
}
//declare an interface with area() as a member
type shape interface {
area() int
}
//declare a method area()
//the rectangle struct implements area() method in shape interface
func (r rectangle) area() int {
return r.length * r.width
}
//declare a method with type shape as a parameter
func info(s shape) {
fmt.Println("the area: ", s.area())
}
func main() {
r1 := rectangle{12, 12}
//r1 is a rectangle type. rectangle implements all methods in shape interface.
info(r1)
}
// output
// the area: 144
根据该示例,我们声明一个矩形的struct和一个形状的interface。 矩形在形状interface中实现了area()。info()以形状类型作为参数。 实现了shape interface中所有方法的struct都可以作为info()的参数。
如果存在另一个struct,称为正方形。 info()方法也可用,因为正方形也可以实现shape接口中的所有方法。
package main
import (
"fmt"
)
//declare a rectangle struct
type rectangle struct {
length int
width int
}
//declare a square struct
type square struct {
side int
}
//declare an interface with area() as a member
type shape interface {
area() int
}
//declare a method area()
//the rectangle struct implements area() method in shape interface
func (r rectangle) area() int {
return r.length * r.width
}
//the square struct implements area() method in shape interface
func (s square) area() int {
return s.side * s.side
}
//declare a method with type shape as a parameter
/**
anything that implements all methods in shape interface is considered as a shape in general.
for this case the rectangle and square is a shape because implements all methods in shape interface
**/
func info(s shape) {
fmt.Println("the area: ", s.area())
}
func main() {
r1 := rectangle{12, 12}
info(r1)
s1 := square{25}
info(s1)
}
// output
// the area: 144
// the area: 625
另外值得注意的是,interface也可以组合。
Method sets
方法集是与特定类型关联的函数。 例如,area()是与shape类型相关联的函数。 如果方法集的接收者是一个值,那么该方法可以被一个值或一个值的指针使用。
例如,area()方法可用于shape的值和指针(在此示例中为矩形)。
package main
import (
"fmt"
)
//shape interface
type shape interface {
area() int
}
func (r rectangle) area() int {
return r.length * r.width
}
//used in info() function
func info(s shape) {
fmt.Println("the area: ", s.area())
}
func main() {
r1 := rectangle{12, 12}
//with value
info(r1)
//with pointer
info(&r1)
}
// output
// the area: 144
// the area: 144
如果方法集的接收者是指针,则该方法仅能用指针调用。
package main
import (
"fmt"
)
//the receiver is a pointer
func (r *rectangle) area() int {
return r.length * r.width
}
func info(s shape) {
fmt.Println("the area: ", s.area())
}
func main() {
r1 := rectangle{12, 12}
// 如果使用值调用,会报错
// info(r1)
//with pointer
info(&r1)
}
// output
// the area: 144
深入学习
我希望本文对帮助学习Go编程语言有所帮助。 如果您有任何想法或反馈,可以在下面的评论留言。
关注公众号【技术全沾】学习更多有趣的编程知识。
Golang基础入门系列:
- 简介
- 常量
- 条件选择
- 循环
- Array,Slice 和 Map
- Function
- Struct 和 Interface
- 错误处理
- 协程
- Channel
- Testing