Go语言虽然不是纯粹的面向对象语言,但它通过结构体(struct)、接口(interface)和方法(method)提供了面向对象编程的能力。下面我将通过具体示例展示Go中如何实现类、封装、继承、多态以及构造函数等概念。
1. 类与封装
在Go中,使用结构体(struct)来定义"类",并通过大小写控制访问权限实现封装。
package mainimport "fmt"// Person 类(结构体)
type Person struct {name string // 小写开头,私有字段(仅在当前包内可访问)Age int // 大写开头,公共字段(可在其他包中访问)
}// NewPerson 构造函数(工厂函数)
// 通常以New开头命名构造函数
func NewPerson(name string, age int) *Person {return &Person{name: name,Age: age,}
}// GetName 获取name的方法(Getter)
// 由于name是私有的,需要通过方法访问
func (p *Person) GetName() string {return p.name
}// SetName 设置name的方法(Setter)
func (p *Person) SetName(name string) {p.name = name
}// Introduce 方法
func (p *Person) Introduce() {fmt.Printf("大家好,我是%s,今年%d岁。\n", p.name, p.Age)
}func main() {// 使用构造函数创建Person实例person := NewPerson("张三", 25)// 访问公共字段fmt.Println("年龄:", person.Age)// 通过方法访问私有字段fmt.Println("姓名:", person.GetName())// 修改私有字段person.SetName("李四")// 调用方法person.Introduce()
}
2. 继承(组合)
Go没有传统意义上的继承,而是通过结构体嵌入(embedding)实现组合。
package mainimport "fmt"// Animal 基类
type Animal struct {name string
}// NewAnimal 构造函数
func NewAnimal(name string) *Animal {return &Animal{name: name}
}// Speak 方法
func (a *Animal) Speak() {fmt.Println(a.name, "发出声音")
}// Eat 方法
func (a *Animal) Eat() {fmt.Println(a.name, "正在吃东西")
}// Dog 继承Animal
type Dog struct {*Animal // 嵌入Animal,相当于继承Breed string // 狗的品种
}// NewDog 构造函数
func NewDog(name, breed string) *Dog {return &Dog{Animal: NewAnimal(name),Breed: breed,}
}// Speak 方法重写
func (d *Dog) Speak() {fmt.Println(d.name, "汪汪叫")
}// Fetch 子类特有方法
func (d *Dog) Fetch() {fmt.Println(d.name, "正在捡球")
}func main() {animal := NewAnimal("普通动物")animal.Speak()animal.Eat()dog := NewDog("阿黄", "金毛")dog.Speak() // 调用重写后的方法dog.Eat() // 调用继承的方法dog.Fetch() // 调用子类特有方法// 通过嵌入字段访问基类字段fmt.Println("狗的名字:", dog.name)fmt.Println("狗的品种:", dog.Breed)
}
3. 多态(接口实现)
Go通过接口(interface)实现多态。
package mainimport "fmt"// Shape 接口
type Shape interface {Area() float64Perimeter() float64
}// Rectangle 矩形类
type Rectangle struct {width, height float64
}// NewRectangle 构造函数
func NewRectangle(width, height float64) *Rectangle {return &Rectangle{width, height}
}// Area 实现Shape接口的方法
func (r *Rectangle) Area() float64 {return r.width * r.height
}// Perimeter 实现Shape接口的方法
func (r *Rectangle) Perimeter() float64 {return 2 * (r.width + r.height)
}// Circle 圆形类
type Circle struct {radius float64
}// NewCircle 构造函数
func NewCircle(radius float64) *Circle {return &Circle{radius}
}// Area 实现Shape接口的方法
func (c *Circle) Area() float64 {return 3.14 * c.radius * c.radius
}// Perimeter 实现Shape接口的方法
func (c *Circle) Perimeter() float64 {return 2 * 3.14 * c.radius
}// PrintShapeInfo 多态函数,接受任何实现了Shape接口的类型
func PrintShapeInfo(s Shape) {fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}func main() {rect := NewRectangle(10, 5)circle := NewCircle(7)// 相同接口,不同表现PrintShapeInfo(rect)PrintShapeInfo(circle)// 接口类型断言if r, ok := rect.(*Rectangle); ok {fmt.Println("这是一个矩形,宽:", r.width, "高:", r.height)}// 类型开关(type switch)var s Shape = circleswitch v := s.(type) {case *Rectangle:fmt.Println("矩形:", v.width, v.height)case *Circle:fmt.Println("圆形,半径:", v.radius)default:fmt.Println("未知形状")}
}
4. 方法实现细节
Go中的方法可以绑定到任何类型(不仅仅是结构体),包括基本类型。
package mainimport ("fmt""math"
)// MyInt 自定义类型
type MyInt int// Double 方法
func (m MyInt) Double() MyInt {return m * 2
}// Point 结构体
type Point struct {X, Y float64
}// DistanceTo 方法(值接收者)
func (p Point) DistanceTo(q Point) float64 {return math.Hypot(q.X-p.X, q.Y-p.Y)
}// Scale 方法(指针接收者,会修改原值)
func (p *Point) Scale(factor float64) {p.X *= factorp.Y *= factor
}// String 方法(实现Stringer接口)
func (p Point) String() string {return fmt.Sprintf("Point{X: %.2f, Y: %.2f}", p.X, p.Y)
}func main() {// 自定义类型方法num := MyInt(5)fmt.Println(num.Double()) // 10// 结构体方法p1 := Point{1, 2}p2 := Point{4, 6}fmt.Println("距离:", p1.DistanceTo(p2)) // 5p1.Scale(2)fmt.Println(p1) // 使用String方法输出: Point{X: 2.00, Y: 4.00}// 指针与值的自动转换p3 := &Point{3, 4}fmt.Println("距离:", p3.DistanceTo(p2)) // Go会自动解引用p2.Scale(0.5) // Go会自动取地址fmt.Println(p2)
}
5. 综合示例
package mainimport ("fmt""strings"
)// Employee 基类
type Employee struct {name stringsalary float64vacation bool
}// NewEmployee 构造函数
func NewEmployee(name string, salary float64) *Employee {return &Employee{name: name,salary: salary,vacation: false,}
}// GetName Getter
func (e *Employee) GetName() string {return e.name
}// GetSalary Getter
func (e *Employee) GetSalary() float64 {return e.salary
}// TakeVacation 方法
func (e *Employee) TakeVacation() {e.vacation = true
}// Work 方法
func (e *Employee) Work() {fmt.Printf("%s 正在工作...\n", e.name)
}// String 方法
func (e *Employee) String() string {return fmt.Sprintf("员工: %s, 薪资: %.2f, 休假中: %v", e.name, e.salary, e.vacation)
}// Developer 子类
type Developer struct {*Employee // 嵌入Employeelanguage string // 开发语言
}// NewDeveloper 构造函数
func NewDeveloper(name string, salary float64, language string) *Developer {return &Developer{Employee: NewEmployee(name, salary),language: language,}
}// Work 方法重写
func (d *Developer) Work() {fmt.Printf("%s 正在用 %s 写代码...\n", d.GetName(), d.language)
}// Debug 特有方法
func (d *Developer) Debug() {fmt.Printf("%s 正在调试 %s 代码...\n", d.GetName(), d.language)
}// Manager 子类
type Manager struct {*Employee // 嵌入Employeeteam []string // 团队成员
}// NewManager 构造函数
func NewManager(name string, salary float64, team []string) *Manager {return &Manager{Employee: NewEmployee(name, salary),team: team,}
}// Work 方法重写
func (m *Manager) Work() {fmt.Printf("%s 正在管理团队: %s\n", m.GetName(), strings.Join(m.team, ", "))
}// ConductMeeting 特有方法
func (m *Manager) ConductMeeting() {fmt.Printf("%s 正在主持会议\n", m.GetName())
}// Worker 接口
type Worker interface {Work()GetName() stringGetSalary() float64
}// Company 公司类
type Company struct {workers []Worker
}// AddWorker 添加员工
func (c *Company) AddWorker(w Worker) {c.workers = append(c.workers, w)
}// StartWorkDay 开始工作日
func (c *Company) StartWorkDay() {fmt.Println("===== 工作日开始 =====")for _, worker := range c.workers {worker.Work()}fmt.Println("===== 工作日结束 =====")
}func main() {// 创建公司company := &Company{}// 创建员工dev1 := NewDeveloper("张三", 15000, "Go")dev2 := NewDeveloper("李四", 16000, "Python")manager := NewManager("王五", 25000, []string{"张三", "李四"})// 员工休假dev1.TakeVacation()// 添加员工到公司company.AddWorker(dev1)company.AddWorker(dev2)company.AddWorker(manager)// 开始工作company.StartWorkDay()// 调用特有方法dev2.Debug()manager.ConductMeeting()// 打印员工信息fmt.Println(dev1)fmt.Println(dev2)fmt.Println(manager)
}
关键概念总结
-
类与封装:Go使用结构体定义类,通过字段/方法名的大小写控制访问权限(大写公开,小写私有)
-
构造函数:Go没有真正的构造函数,通常使用
NewXxx
形式的工厂函数 -
继承:通过结构体嵌入实现组合式继承
-
多态:通过接口实现,任何实现了接口所有方法的类型都自动满足该接口
-
方法:可以绑定到任何类型,接收者可以是值或指针
-
接口:定义行为而非实现,是实现多态的关键
Go的面向对象方式与传统OOP语言有所不同,它更强调组合而非继承,通过接口实现多态,这种方式更灵活且避免了传统继承的许多问题。