面向对象编程
2026/3/20大约 11 分钟
面向对象编程
一、Go 的 OOP 哲学
Go 语言没有传统的类(class)和继承(inheritance),而是通过组合(composition)和接口(interface)实现面向对象编程。
传统 OOP vs Go OOP
├── 传统语言(Java/C++/Python)
│ ├── class 定义类
│ ├── extends 继承
│ ├── implements 显式实现接口
│ ├── abstract 抽象类
│ └── private/protected/public 访问控制
│
└── Go 语言
├── struct 定义类型
├── 嵌入(embedding)代替继承
├── 隐式接口实现
├── 没有抽象类(使用接口代替)
└── 大小写控制可见性
二、接口(Interface)
2.1 接口基础
package main
import (
"fmt"
"math"
)
// 定义接口
type Shape interface {
Area() float64
Perimeter() float64
}
// 实现接口的结构体(隐式实现,无需声明)
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// 使用接口作为参数
func printShapeInfo(s Shape) {
fmt.Printf("类型: %T\n", s)
fmt.Printf("面积: %.2f\n", s.Area())
fmt.Printf("周长: %.2f\n", s.Perimeter())
fmt.Println("---")
}
func main() {
shapes := []Shape{
Circle{Radius: 5},
Rectangle{Width: 4, Height: 6},
}
for _, shape := range shapes {
printShapeInfo(shape)
}
}
2.2 运维场景接口设计
package main
import (
"fmt"
"strings"
"time"
)
// ========== 健康检查接口 ==========
type HealthChecker interface {
Check() HealthResult
Name() string
}
type HealthResult struct {
Healthy bool
Message string
Latency time.Duration
}
// HTTP 检查
type HTTPChecker struct {
URL string
Timeout time.Duration
}
func (h HTTPChecker) Name() string {
return fmt.Sprintf("HTTP(%s)", h.URL)
}
func (h HTTPChecker) Check() HealthResult {
start := time.Now()
// 模拟 HTTP 检查
latency := time.Since(start)
return HealthResult{
Healthy: true,
Message: "200 OK",
Latency: latency,
}
}
// TCP 检查
type TCPChecker struct {
Host string
Port int
}
func (t TCPChecker) Name() string {
return fmt.Sprintf("TCP(%s:%d)", t.Host, t.Port)
}
func (t TCPChecker) Check() HealthResult {
start := time.Now()
latency := time.Since(start)
return HealthResult{
Healthy: true,
Message: "connection established",
Latency: latency,
}
}
// DNS 检查
type DNSChecker struct {
Domain string
}
func (d DNSChecker) Name() string {
return fmt.Sprintf("DNS(%s)", d.Domain)
}
func (d DNSChecker) Check() HealthResult {
start := time.Now()
latency := time.Since(start)
return HealthResult{
Healthy: true,
Message: "resolved",
Latency: latency,
}
}
// ========== 通知接口 ==========
type Notifier interface {
Send(title, message string) error
}
type EmailNotifier struct {
To string
From string
}
func (e EmailNotifier) Send(title, message string) error {
fmt.Printf("[Email] To: %s, Subject: %s\n", e.To, title)
return nil
}
type DingTalkNotifier struct {
WebhookURL string
}
func (d DingTalkNotifier) Send(title, message string) error {
fmt.Printf("[DingTalk] Webhook: %s, Title: %s\n", d.WebhookURL, title)
return nil
}
type SlackNotifier struct {
Channel string
Token string
}
func (s SlackNotifier) Send(title, message string) error {
fmt.Printf("[Slack] Channel: %s, Title: %s\n", s.Channel, title)
return nil
}
// ========== 健康检查引擎 ==========
type HealthCheckEngine struct {
checkers []HealthChecker
notifiers []Notifier
}
func NewHealthCheckEngine() *HealthCheckEngine {
return &HealthCheckEngine{}
}
func (e *HealthCheckEngine) AddChecker(checkers ...HealthChecker) {
e.checkers = append(e.checkers, checkers...)
}
func (e *HealthCheckEngine) AddNotifier(notifiers ...Notifier) {
e.notifiers = append(e.notifiers, notifiers...)
}
func (e *HealthCheckEngine) RunAll() {
var failures []string
for _, checker := range e.checkers {
result := checker.Check()
status := "OK"
if !result.Healthy {
status = "FAIL"
failures = append(failures, checker.Name())
}
fmt.Printf("[%s] %s - %s (%v)\n",
status, checker.Name(), result.Message, result.Latency)
}
// 如果有失败,发送通知
if len(failures) > 0 {
title := "健康检查告警"
message := "以下检查失败: " + strings.Join(failures, ", ")
for _, notifier := range e.notifiers {
notifier.Send(title, message)
}
}
}
func main() {
engine := NewHealthCheckEngine()
// 添加检查器(不同实现,统一接口)
engine.AddChecker(
HTTPChecker{URL: "http://api.example.com/health", Timeout: 5 * time.Second},
TCPChecker{Host: "db.example.com", Port: 3306},
DNSChecker{Domain: "example.com"},
)
// 添加通知器
engine.AddNotifier(
EmailNotifier{To: "ops@company.com", From: "monitor@company.com"},
DingTalkNotifier{WebhookURL: "https://oapi.dingtalk.com/robot/send?token=xxx"},
)
// 运行检查
engine.RunAll()
}
2.3 接口组合
package main
import (
"fmt"
"io"
)
// 小接口组合成大接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
// 标准库中的经典接口组合
// io.ReadWriter = io.Reader + io.Writer
// io.ReadCloser = io.Reader + io.Closer
// io.ReadWriteCloser = io.Reader + io.Writer + io.Closer
// 运维场景:日志处理接口
type LogReader interface {
ReadLog(path string) ([]string, error)
}
type LogWriter interface {
WriteLog(path string, lines []string) error
}
type LogRotator interface {
Rotate(path string) error
}
// 完整的日志管理器接口
type LogManager interface {
LogReader
LogWriter
LogRotator
}
// 实现
type FileLogManager struct {
MaxSize int64
}
func (f *FileLogManager) ReadLog(path string) ([]string, error) {
fmt.Printf("读取日志: %s\n", path)
return []string{"line1", "line2"}, nil
}
func (f *FileLogManager) WriteLog(path string, lines []string) error {
fmt.Printf("写入 %d 行到: %s\n", len(lines), path)
return nil
}
func (f *FileLogManager) Rotate(path string) error {
fmt.Printf("轮转日志: %s\n", path)
return nil
}
// 只需要读功能的函数
func analyze(reader LogReader, path string) {
lines, _ := reader.ReadLog(path)
fmt.Printf("分析了 %d 行\n", len(lines))
}
func main() {
manager := &FileLogManager{MaxSize: 100 * 1024 * 1024}
// 作为完整接口使用
var lm LogManager = manager
lm.ReadLog("/var/log/app.log")
lm.Rotate("/var/log/app.log")
// 作为子接口使用(接口越小越灵活)
analyze(manager, "/var/log/app.log")
// 标准库接口示例
_ = io.Discard // io.Writer 的实现,丢弃所有写入
}
2.4 空接口与类型断言
package main
import (
"fmt"
)
// 空接口可以接受任何类型(Go 1.18+ 推荐用 any)
func printValue(v any) {
// 类型断言
switch val := v.(type) {
case nil:
fmt.Println("nil")
case int:
fmt.Printf("int: %d\n", val)
case float64:
fmt.Printf("float64: %.2f\n", val)
case string:
fmt.Printf("string: %q\n", val)
case bool:
fmt.Printf("bool: %v\n", val)
case []int:
fmt.Printf("[]int: %v\n", val)
case map[string]any:
fmt.Printf("map: %v\n", val)
default:
fmt.Printf("unknown type %T: %v\n", val, val)
}
}
// 安全的类型断言
func toString(v any) (string, bool) {
s, ok := v.(string)
return s, ok
}
// 运维场景:处理 JSON 配置
func processConfig(config map[string]any) {
for key, value := range config {
switch v := value.(type) {
case string:
fmt.Printf(" %s (string) = %s\n", key, v)
case float64: // JSON 数字默认解析为 float64
fmt.Printf(" %s (number) = %.0f\n", key, v)
case bool:
fmt.Printf(" %s (bool) = %v\n", key, v)
case map[string]any:
fmt.Printf(" %s (object):\n", key)
for k, val := range v {
fmt.Printf(" %s = %v\n", k, val)
}
case []any:
fmt.Printf(" %s (array) = %v\n", key, v)
}
}
}
func main() {
printValue(42)
printValue("hello")
printValue(3.14)
printValue(true)
printValue(nil)
// 安全断言
if s, ok := toString("hello"); ok {
fmt.Println("转换成功:", s)
}
if _, ok := toString(42); !ok {
fmt.Println("不是字符串")
}
// 处理 JSON 配置
config := map[string]any{
"host": "localhost",
"port": float64(8080),
"debug": true,
"servers": []any{"web-01", "web-02"},
"limits": map[string]any{
"max_conn": float64(1000),
"timeout": float64(30),
},
}
fmt.Println("配置:")
processConfig(config)
}
2.5 常见接口模式
package main
import (
"fmt"
"io"
"strings"
)
// ========== Stringer 接口 ==========
type Server struct {
Name string
IP string
Port int
Status string
}
func (s Server) String() string {
return fmt.Sprintf("%s(%s:%d)[%s]", s.Name, s.IP, s.Port, s.Status)
}
// ========== error 接口 ==========
type AppError struct {
Code int
Message string
Cause error
}
func (e *AppError) Error() string {
if e.Cause != nil {
return fmt.Sprintf("[%d] %s: %v", e.Code, e.Message, e.Cause)
}
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}
func (e *AppError) Unwrap() error {
return e.Cause
}
// ========== io.Writer 接口 ==========
type PrefixWriter struct {
Prefix string
Writer io.Writer
}
func (pw *PrefixWriter) Write(p []byte) (n int, err error) {
lines := strings.Split(string(p), "\n")
for _, line := range lines {
if line != "" {
fmt.Fprintf(pw.Writer, "%s %s\n", pw.Prefix, line)
}
}
return len(p), nil
}
// ========== Sort 接口 ==========
type ServerList []Server
func (sl ServerList) Len() int { return len(sl) }
func (sl ServerList) Less(i, j int) bool { return sl[i].Name < sl[j].Name }
func (sl ServerList) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func main() {
// Stringer
s := Server{"web-01", "10.0.0.1", 8080, "running"}
fmt.Println(s) // 自动调用 String()
// Error
err := &AppError{
Code: 500,
Message: "database connection failed",
Cause: fmt.Errorf("timeout after 30s"),
}
fmt.Println(err)
// io.Writer
pw := &PrefixWriter{
Prefix: "[INFO]",
Writer: &strings.Builder{},
}
fmt.Fprint(pw, "服务器启动\n数据库已连接\n")
}
三、嵌入与组合
3.1 结构体嵌入
package main
import (
"fmt"
"time"
)
// 基础结构体
type BaseModel struct {
ID int64
CreatedAt time.Time
UpdatedAt time.Time
}
func (b *BaseModel) SetTimestamps() {
now := time.Now()
if b.CreatedAt.IsZero() {
b.CreatedAt = now
}
b.UpdatedAt = now
}
// 嵌入基础结构体
type User struct {
BaseModel
Name string
Email string
}
type Server struct {
BaseModel
Hostname string
IP string
Status string
}
// 多层嵌入
type Metadata struct {
Labels map[string]string
Annotations map[string]string
}
type KubeResource struct {
BaseModel
Metadata
Namespace string
Kind string
}
func main() {
// 可以直接访问嵌入字段
user := User{
Name: "admin",
Email: "admin@example.com",
}
user.SetTimestamps() // 调用 BaseModel 的方法
user.ID = 1 // 直接访问嵌入字段
fmt.Printf("User: %s (ID: %d, Created: %v)\n",
user.Name, user.ID, user.CreatedAt.Format("2006-01-02"))
// K8s 资源
resource := KubeResource{
Namespace: "default",
Kind: "Deployment",
Metadata: Metadata{
Labels: map[string]string{
"app": "nginx",
"tier": "frontend",
},
},
}
resource.SetTimestamps()
resource.ID = 100
fmt.Printf("Resource: %s/%s (Labels: %v)\n",
resource.Namespace, resource.Kind, resource.Labels)
}
3.2 接口嵌入实现装饰器模式
package main
import (
"fmt"
"io"
"strings"
"time"
)
// ========== 装饰器模式 ==========
// 基础 Writer
type LogWriter struct {
Output io.Writer
}
func (lw *LogWriter) Write(p []byte) (n int, err error) {
return lw.Output.Write(p)
}
// 时间戳装饰器
type TimestampWriter struct {
io.Writer // 嵌入接口
}
func NewTimestampWriter(w io.Writer) *TimestampWriter {
return &TimestampWriter{Writer: w}
}
func (tw *TimestampWriter) Write(p []byte) (n int, err error) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
prefix := []byte(fmt.Sprintf("[%s] ", timestamp))
data := append(prefix, p...)
return tw.Writer.Write(data)
}
// 级别装饰器
type LevelWriter struct {
io.Writer
Level string
}
func NewLevelWriter(w io.Writer, level string) *LevelWriter {
return &LevelWriter{Writer: w, Level: level}
}
func (lw *LevelWriter) Write(p []byte) (n int, err error) {
prefix := []byte(fmt.Sprintf("[%s] ", lw.Level))
data := append(prefix, p...)
return lw.Writer.Write(data)
}
func main() {
var output strings.Builder
// 链式装饰
writer := NewTimestampWriter(
NewLevelWriter(&output, "INFO"),
)
fmt.Fprint(writer, "服务器启动成功\n")
fmt.Fprint(writer, "开始监听端口 8080\n")
fmt.Print(output.String())
// [2024-01-15 10:30:00] [INFO] 服务器启动成功
// [2024-01-15 10:30:00] [INFO] 开始监听端口 8080
}
四、泛型(Go 1.18+)
4.1 泛型基础
package main
import (
"cmp"
"fmt"
)
// 泛型函数
func Max[T cmp.Ordered](a, b T) T {
if a > b {
return a
}
return b
}
func Min[T cmp.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
// 泛型切片操作
func Contains[T comparable](slice []T, target T) bool {
for _, v := range slice {
if v == target {
return true
}
}
return false
}
func Filter[T any](slice []T, predicate func(T) bool) []T {
result := make([]T, 0)
for _, v := range slice {
if predicate(v) {
result = append(result, v)
}
}
return result
}
func Map[T any, U any](slice []T, transform func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = transform(v)
}
return result
}
func Reduce[T any, U any](slice []T, initial U, fn func(U, T) U) U {
result := initial
for _, v := range slice {
result = fn(result, v)
}
return result
}
func main() {
// 泛型函数调用
fmt.Println("Max(3, 5):", Max(3, 5))
fmt.Println("Max(3.14, 2.71):", Max(3.14, 2.71))
fmt.Println("Max(a, z):", Max("a", "z"))
// Contains
servers := []string{"web-01", "web-02", "web-03"}
fmt.Println("包含 web-02:", Contains(servers, "web-02"))
fmt.Println("包含 web-04:", Contains(servers, "web-04"))
// Filter
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evens := Filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Println("偶数:", evens)
// Map
doubled := Map(numbers, func(n int) int {
return n * 2
})
fmt.Println("翻倍:", doubled)
// Reduce
sum := Reduce(numbers, 0, func(acc, n int) int {
return acc + n
})
fmt.Println("总和:", sum)
// 字符串长度映射
lengths := Map(servers, func(s string) int {
return len(s)
})
fmt.Println("名称长度:", lengths)
}
4.2 泛型约束
package main
import (
"fmt"
"strings"
)
// 自定义约束接口
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64
}
type Stringable interface {
~string
}
// 使用约束
func Sum[T Number](nums []T) T {
var total T
for _, n := range nums {
total += n
}
return total
}
// 结构体约束
type HasName interface {
GetName() string
}
type Server struct {
Name string
IP string
}
func (s Server) GetName() string { return s.Name }
type Service struct {
Name string
Port int
}
func (s Service) GetName() string { return s.Name }
// 泛型函数使用结构体约束
func FindByName[T HasName](items []T, name string) (T, bool) {
for _, item := range items {
if item.GetName() == name {
return item, true
}
}
var zero T
return zero, false
}
func PrintNames[T HasName](items []T) {
names := make([]string, len(items))
for i, item := range items {
names[i] = item.GetName()
}
fmt.Println(strings.Join(names, ", "))
}
func main() {
// Number 约束
ints := []int{1, 2, 3, 4, 5}
fmt.Println("整数和:", Sum(ints))
floats := []float64{1.1, 2.2, 3.3}
fmt.Println("浮点和:", Sum(floats))
// 结构体约束
servers := []Server{
{Name: "web-01", IP: "10.0.0.1"},
{Name: "web-02", IP: "10.0.0.2"},
}
services := []Service{
{Name: "nginx", Port: 80},
{Name: "mysql", Port: 3306},
}
if s, ok := FindByName(servers, "web-01"); ok {
fmt.Printf("找到服务器: %s (%s)\n", s.Name, s.IP)
}
if svc, ok := FindByName(services, "mysql"); ok {
fmt.Printf("找到服务: %s (port: %d)\n", svc.Name, svc.Port)
}
fmt.Print("服务器: ")
PrintNames(servers)
fmt.Print("服务: ")
PrintNames(services)
}
4.3 泛型结构体
package main
import (
"fmt"
"sync"
)
// ========== 泛型栈 ==========
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item, true
}
func (s *Stack[T]) Peek() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
return s.items[len(s.items)-1], true
}
func (s *Stack[T]) Size() int {
return len(s.items)
}
// ========== 泛型线程安全缓存 ==========
type Cache[K comparable, V any] struct {
mu sync.RWMutex
items map[K]V
}
func NewCache[K comparable, V any]() *Cache[K, V] {
return &Cache[K, V]{
items: make(map[K]V),
}
}
func (c *Cache[K, V]) Set(key K, value V) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = value
}
func (c *Cache[K, V]) Get(key K) (V, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
val, ok := c.items[key]
return val, ok
}
func (c *Cache[K, V]) Delete(key K) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.items, key)
}
func (c *Cache[K, V]) Size() int {
c.mu.RLock()
defer c.mu.RUnlock()
return len(c.items)
}
// ========== 泛型结果类型 ==========
type Result[T any] struct {
Value T
Err error
}
func NewResult[T any](value T, err error) Result[T] {
return Result[T]{Value: value, Err: err}
}
func (r Result[T]) IsOK() bool {
return r.Err == nil
}
func (r Result[T]) Unwrap() T {
if r.Err != nil {
panic(fmt.Sprintf("unwrap on error: %v", r.Err))
}
return r.Value
}
func (r Result[T]) UnwrapOr(defaultVal T) T {
if r.Err != nil {
return defaultVal
}
return r.Value
}
func main() {
// 使用泛型栈
intStack := &Stack[int]{}
intStack.Push(1)
intStack.Push(2)
intStack.Push(3)
for intStack.Size() > 0 {
val, _ := intStack.Pop()
fmt.Println("弹出:", val)
}
// 字符串栈
strStack := &Stack[string]{}
strStack.Push("task-1")
strStack.Push("task-2")
if top, ok := strStack.Peek(); ok {
fmt.Println("栈顶:", top)
}
// 使用泛型缓存
serverCache := NewCache[string, string]()
serverCache.Set("web-01", "10.0.0.1")
serverCache.Set("web-02", "10.0.0.2")
if ip, ok := serverCache.Get("web-01"); ok {
fmt.Println("web-01 IP:", ip)
}
// 数字缓存
metricCache := NewCache[string, float64]()
metricCache.Set("cpu", 75.5)
metricCache.Set("memory", 60.2)
fmt.Println("缓存大小:", metricCache.Size())
// Result 类型
r1 := NewResult("success", nil)
r2 := NewResult("", fmt.Errorf("failed"))
fmt.Println("r1:", r1.Unwrap())
fmt.Println("r2:", r2.UnwrapOr("default"))
}
五、设计模式实战
5.1 策略模式
package main
import (
"fmt"
"math/rand"
)
// 负载均衡策略接口
type LoadBalancer interface {
Select(servers []string) string
}
// 轮询策略
type RoundRobin struct {
current int
}
func (rr *RoundRobin) Select(servers []string) string {
if len(servers) == 0 {
return ""
}
server := servers[rr.current%len(servers)]
rr.current++
return server
}
// 随机策略
type Random struct{}
func (r *Random) Select(servers []string) string {
if len(servers) == 0 {
return ""
}
return servers[rand.Intn(len(servers))]
}
// 权重策略
type Weighted struct {
Weights map[string]int
}
func (w *Weighted) Select(servers []string) string {
totalWeight := 0
for _, s := range servers {
totalWeight += w.Weights[s]
}
r := rand.Intn(totalWeight)
for _, s := range servers {
r -= w.Weights[s]
if r < 0 {
return s
}
}
return servers[0]
}
// 使用策略
type Proxy struct {
servers []string
balancer LoadBalancer
}
func NewProxy(servers []string, balancer LoadBalancer) *Proxy {
return &Proxy{servers: servers, balancer: balancer}
}
func (p *Proxy) Forward() string {
selected := p.balancer.Select(p.servers)
return selected
}
func main() {
servers := []string{"web-01", "web-02", "web-03"}
// 使用轮询
proxy := NewProxy(servers, &RoundRobin{})
fmt.Println("轮询策略:")
for i := 0; i < 6; i++ {
fmt.Printf(" 请求 %d -> %s\n", i+1, proxy.Forward())
}
// 使用随机
proxy = NewProxy(servers, &Random{})
fmt.Println("\n随机策略:")
for i := 0; i < 6; i++ {
fmt.Printf(" 请求 %d -> %s\n", i+1, proxy.Forward())
}
}
六、本章小结
| 主题 | 核心要点 |
|---|---|
| 接口 | 隐式实现,面向行为编程 |
| 接口组合 | 小接口组合成大接口,遵循 ISP |
| 嵌入组合 | 代替继承,实现代码复用 |
| 空接口 | any 接受任意类型,配合类型断言使用 |
| 泛型 | Go 1.18+,类型参数化,约束接口 |
| 设计模式 | 策略模式、装饰器模式、工厂模式 |
运维开发建议
- 接口设计遵循单一职责,小接口优于大接口
- 使用组合代替继承,保持代码扁平
- 泛型适合通用数据结构和工具函数
- 运维工具中大量使用策略模式(如负载均衡、健康检查)