初始提交

This commit is contained in:
2025-08-24 01:01:26 +08:00
commit e51feb1296
35 changed files with 9348 additions and 0 deletions

View File

@@ -0,0 +1,869 @@
/*
05-methods.go - Go 语言方法详解
学习目标:
1. 理解方法与函数的区别
2. 掌握方法的定义和调用
3. 学会值接收者和指针接收者的使用
4. 了解方法集的概念
5. 掌握方法的实际应用
知识点:
- 方法定义语法
- 值接收者 vs 指针接收者
- 方法集和接口实现
- 方法的继承和组合
- 方法的实际应用场景
*/
package main
import (
"fmt"
)
func main() {
fmt.Println("=== Go 语言方法详解 ===\n")
// 演示基本方法定义和调用
demonstrateBasicMethods()
// 演示值接收者和指针接收者
demonstrateReceiverTypes()
// 演示方法集和接口实现
demonstrateMethodSets()
// 演示方法的继承和组合
demonstrateMethodComposition()
// 演示方法的实际应用
demonstratePracticalApplications()
// 演示方法的高级用法
demonstrateAdvancedMethodUsage()
}
// demonstrateBasicMethods 演示基本方法定义和调用
func demonstrateBasicMethods() {
fmt.Println("1. 基本方法定义和调用:")
// 创建结构体实例
fmt.Printf(" 创建和使用基本方法:\n")
rect := Rectangle{Width: 10, Height: 5}
fmt.Printf(" 矩形: %+v\n", rect)
fmt.Printf(" 面积: %.2f\n", rect.Area())
fmt.Printf(" 周长: %.2f\n", rect.Perimeter())
// 方法链调用
fmt.Printf(" 方法链调用:\n")
rect.SetWidth(8).SetHeight(6)
fmt.Printf(" 修改后的矩形: %+v\n", rect)
fmt.Printf(" 新面积: %.2f\n", rect.Area())
// 不同类型的方法
fmt.Printf(" 不同类型的方法:\n")
circle := Circle{Radius: 3}
fmt.Printf(" 圆形: %+v\n", circle)
fmt.Printf(" 面积: %.2f\n", circle.Area())
fmt.Printf(" 周长: %.2f\n", circle.Circumference())
// 基本类型的方法
fmt.Printf(" 基本类型的方法:\n")
var temp Temperature = 25.5
fmt.Printf(" 温度: %.1f°C\n", temp)
fmt.Printf(" 华氏度: %.1f°F\n", temp.ToFahrenheit())
fmt.Printf(" 开尔文: %.1f K\n", temp.ToKelvin())
fmt.Println()
}// demonstr
ateReceiverTypes 演示值接收者和指针接收者
func demonstrateReceiverTypes() {
fmt.Println("2. 值接收者和指针接收者:")
// 值接收者示例
fmt.Printf(" 值接收者示例:\n")
counter1 := Counter{Value: 0}
fmt.Printf(" 初始计数器: %+v\n", counter1)
// 值接收者方法不会修改原始值
counter1.IncrementByValue()
fmt.Printf(" 值接收者增加后: %+v\n", counter1) // 值不变
// 指针接收者示例
fmt.Printf(" 指针接收者示例:\n")
counter2 := Counter{Value: 0}
fmt.Printf(" 初始计数器: %+v\n", counter2)
// 指针接收者方法会修改原始值
counter2.IncrementByPointer()
fmt.Printf(" 指针接收者增加后: %+v\n", counter2) // 值改变
// 方法调用的自动转换
fmt.Printf(" 方法调用的自动转换:\n")
counter3 := Counter{Value: 10}
counterPtr := &counter3
// 值类型可以调用指针接收者方法(自动取地址)
counter3.IncrementByPointer()
fmt.Printf(" 值类型调用指针方法: %+v\n", counter3)
// 指针类型可以调用值接收者方法(自动解引用)
result := counterPtr.GetValueCopy()
fmt.Printf(" 指针类型调用值方法: %d\n", result)
// 大结构体的性能考虑
fmt.Printf(" 大结构体的性能考虑:\n")
largeStruct := LargeStruct{}
for i := 0; i < 1000; i++ {
largeStruct.Data[i] = i
}
// 值接收者会拷贝整个结构体
start := time.Now()
largeStruct.ProcessByValue()
valueTime := time.Since(start)
// 指针接收者只传递指针
start = time.Now()
largeStruct.ProcessByPointer()
pointerTime := time.Since(start)
fmt.Printf(" 值接收者耗时: %v\n", valueTime)
fmt.Printf(" 指针接收者耗时: %v\n", pointerTime)
fmt.Println()
}
// demonstrateMethodSets 演示方法集和接口实现
func demonstrateMethodSets() {
fmt.Println("3. 方法集和接口实现:")
// 接口实现
fmt.Printf(" 接口实现:\n")
var shapes []Shape
shapes = append(shapes, Rectangle{Width: 4, Height: 3})
shapes = append(shapes, Circle{Radius: 2})
shapes = append(shapes, Triangle{Base: 6, Height: 4})
totalArea := 0.0
for i, shape := range shapes {
area := shape.Area()
fmt.Printf(" 形状 %d 面积: %.2f\n", i+1, area)
totalArea += area
}
fmt.Printf(" 总面积: %.2f\n", totalArea)
// 方法集的规则
fmt.Printf(" 方法集的规则:\n")
// 值类型的方法集
var drawable1 Drawable = Rectangle{Width: 5, Height: 3}
drawable1.Draw()
// 指针类型的方法集
rect := Rectangle{Width: 5, Height: 3}
var drawable2 Drawable = &rect
drawable2.Draw()
// 可修改接口
fmt.Printf(" 可修改接口:\n")
var modifiable Modifiable = &rect
fmt.Printf(" 修改前: %+v\n", rect)
modifiable.Modify()
fmt.Printf(" 修改后: %+v\n", rect)
// 注意:值类型不能实现需要指针接收者的接口
// var modifiable2 Modifiable = rect // 编译错误
fmt.Println()
}
// demonstrateMethodComposition 演示方法的继承和组合
func demonstrateMethodComposition() {
fmt.Println("4. 方法的继承和组合:")
// 结构体嵌入
fmt.Printf(" 结构体嵌入:\n")
person := Person{
Name: "Alice",
Age: 30,
}
employee := Employee{
Person: person,
JobTitle: "软件工程师",
Salary: 80000,
}
// 可以直接调用嵌入类型的方法
fmt.Printf(" 员工信息: %s\n", employee.GetInfo())
fmt.Printf(" 员工详情: %s\n", employee.GetDetails())
// 匿名嵌入
fmt.Printf(" 匿名嵌入:\n")
manager := Manager{
Person: Person{
Name: "Bob",
Age: 35,
},
Department: "技术部",
TeamSize: 10,
}
// 直接访问嵌入类型的方法和字段
fmt.Printf(" 经理姓名: %s\n", manager.Name) // 直接访问嵌入字段
fmt.Printf(" 经理信息: %s\n", manager.GetInfo()) // 直接调用嵌入方法
fmt.Printf(" 管理信息: %s\n", manager.Manage())
// 方法重写
fmt.Printf(" 方法重写:\n")
student := Student{
Person: Person{
Name: "Charlie",
Age: 20,
},
School: "清华大学",
Grade: "大三",
}
// Student 重写了 GetInfo 方法
fmt.Printf(" 学生信息: %s\n", student.GetInfo())
// 仍然可以访问原始方法
fmt.Printf(" 基础信息: %s\n", student.Person.GetInfo())
fmt.Println()
}// dem
onstratePracticalApplications 演示方法的实际应用
func demonstratePracticalApplications() {
fmt.Println("5. 方法的实际应用:")
// 应用1: 银行账户管理
fmt.Printf(" 应用1 - 银行账户管理:\n")
account := BankAccount{
AccountNumber: "123456789",
Balance: 1000.0,
Owner: "Alice",
}
fmt.Printf(" 初始账户: %s\n", account.GetInfo())
account.Deposit(500.0)
fmt.Printf(" 存款后: %s\n", account.GetInfo())
success := account.Withdraw(200.0)
fmt.Printf(" 取款成功: %t, 余额: %.2f\n", success, account.Balance)
success = account.Withdraw(2000.0)
fmt.Printf(" 取款成功: %t, 余额: %.2f\n", success, account.Balance)
// 应用2: 购物车系统
fmt.Printf(" 应用2 - 购物车系统:\n")
cart := ShoppingCart{}
cart.AddItem("笔记本电脑", 5999.99, 1)
cart.AddItem("鼠标", 99.99, 2)
cart.AddItem("键盘", 299.99, 1)
fmt.Printf(" 购物车内容:\n")
cart.DisplayItems()
fmt.Printf(" 总价: %.2f\n", cart.GetTotal())
cart.RemoveItem("鼠标")
fmt.Printf(" 移除鼠标后总价: %.2f\n", cart.GetTotal())
// 应用3: 日志记录器
fmt.Printf(" 应用3 - 日志记录器:\n")
logger := Logger{Level: "INFO"}
logger.Info("应用程序启动")
logger.Warning("配置文件使用默认值")
logger.Error("数据库连接失败")
logger.Debug("调试信息") // 不会显示,因为级别是 INFO
logger.SetLevel("DEBUG")
logger.Debug("现在可以看到调试信息了")
// 应用4: 配置管理器
fmt.Printf(" 应用4 - 配置管理器:\n")
config := Config{
settings: make(map[string]string),
}
config.Set("database.host", "localhost")
config.Set("database.port", "5432")
config.Set("app.debug", "true")
fmt.Printf(" 数据库主机: %s\n", config.Get("database.host"))
fmt.Printf(" 应用调试: %s\n", config.Get("app.debug"))
fmt.Printf(" 不存在的配置: %s\n", config.Get("nonexistent"))
fmt.Printf(" 所有配置:\n")
config.DisplayAll()
fmt.Println()
}
// demonstrateAdvancedMethodUsage 演示方法的高级用法
func demonstrateAdvancedMethodUsage() {
fmt.Println("6. 方法的高级用法:")
// 高级用法1: 方法表达式
fmt.Printf(" 高级用法1 - 方法表达式:\n")
rect := Rectangle{Width: 4, Height: 3}
// 方法表达式:将方法转换为函数
areaFunc := Rectangle.Area
perimeterFunc := Rectangle.Perimeter
fmt.Printf(" 使用方法表达式计算面积: %.2f\n", areaFunc(rect))
fmt.Printf(" 使用方法表达式计算周长: %.2f\n", perimeterFunc(rect))
// 高级用法2: 方法值
fmt.Printf(" 高级用法2 - 方法值:\n")
// 方法值:绑定到特定实例的方法
rectAreaMethod := rect.Area
rectPerimeterMethod := rect.Perimeter
fmt.Printf(" 使用方法值计算面积: %.2f\n", rectAreaMethod())
fmt.Printf(" 使用方法值计算周长: %.2f\n", rectPerimeterMethod())
// 高级用法3: 接口组合
fmt.Printf(" 高级用法3 - 接口组合:\n")
var readWriter ReadWriter = &File{Name: "test.txt"}
data := []byte("Hello, World!")
readWriter.Write(data)
buffer := make([]byte, 20)
n := readWriter.Read(buffer)
fmt.Printf(" 读取到 %d 字节: %s\n", n, string(buffer[:n]))
// 高级用法4: 类型断言和方法调用
fmt.Printf(" 高级用法4 - 类型断言和方法调用:\n")
var shape Shape = Circle{Radius: 5}
// 类型断言获取具体类型
if circle, ok := shape.(Circle); ok {
fmt.Printf(" 圆的半径: %.2f\n", circle.Radius)
fmt.Printf(" 圆的周长: %.2f\n", circle.Circumference())
}
// 高级用法5: 方法集的动态调用
fmt.Printf(" 高级用法5 - 方法集的动态调用:\n")
calculator := Calculator{}
operations := []struct {
name string
method func(float64, float64) float64
}{
{"加法", calculator.Add},
{"减法", calculator.Subtract},
{"乘法", calculator.Multiply},
{"除法", calculator.Divide},
}
a, b := 10.0, 3.0
for _, op := range operations {
result := op.method(a, b)
fmt.Printf(" %.1f %s %.1f = %.2f\n", a, op.name, b, result)
}
// 高级用法6: 链式方法调用
fmt.Printf(" 高级用法6 - 链式方法调用:\n")
builder := NewStringBuilder()
result := builder.
Append("Hello").
Append(" ").
Append("World").
Append("!").
ToUpper().
Build()
fmt.Printf(" 构建结果: %s\n", result)
fmt.Println()
}// =
========= 类型和方法定义 ==========
// 基本结构体和方法
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// 指针接收者方法,支持方法链
func (r *Rectangle) SetWidth(width float64) *Rectangle {
r.Width = width
return r
}
func (r *Rectangle) SetHeight(height float64) *Rectangle {
r.Height = height
return r
}
func (r Rectangle) Draw() {
fmt.Printf(" 绘制矩形: %.1f x %.1f\n", r.Width, r.Height)
}
func (r *Rectangle) Modify() {
r.Width *= 1.1
r.Height *= 1.1
fmt.Printf(" 矩形已放大 10%%\n")
}
// 圆形结构体和方法
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Circumference() float64 {
return 2 * math.Pi * c.Radius
}
func (c Circle) Draw() {
fmt.Printf(" 绘制圆形: 半径 %.1f\n", c.Radius)
}
// 三角形结构体和方法
type Triangle struct {
Base float64
Height float64
}
func (t Triangle) Area() float64 {
return 0.5 * t.Base * t.Height
}
func (t Triangle) Draw() {
fmt.Printf(" 绘制三角形: 底边 %.1f, 高 %.1f\n", t.Base, t.Height)
}
// 基本类型的方法
type Temperature float64
func (t Temperature) ToFahrenheit() float64 {
return float64(t)*9/5 + 32
}
func (t Temperature) ToKelvin() float64 {
return float64(t) + 273.15
}
// 值接收者 vs 指针接收者示例
type Counter struct {
Value int
}
// 值接收者:不会修改原始值
func (c Counter) IncrementByValue() {
c.Value++
fmt.Printf(" 值接收者内部: %d\n", c.Value)
}
// 指针接收者:会修改原始值
func (c *Counter) IncrementByPointer() {
c.Value++
fmt.Printf(" 指针接收者内部: %d\n", c.Value)
}
func (c Counter) GetValueCopy() int {
return c.Value
}
// 大结构体性能测试
type LargeStruct struct {
Data [1000]int
}
func (ls LargeStruct) ProcessByValue() {
// 值接收者会拷贝整个结构体
sum := 0
for _, v := range ls.Data {
sum += v
}
}
func (ls *LargeStruct) ProcessByPointer() {
// 指针接收者只传递指针
sum := 0
for _, v := range ls.Data {
sum += v
}
}
// 接口定义
type Shape interface {
Area() float64
}
type Drawable interface {
Draw()
}
type Modifiable interface {
Modify()
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type Reader interface {
Read([]byte) int
}
type Writer interface {
Write([]byte) int
}
// 文件类型实现 ReadWriter 接口
type File struct {
Name string
data []byte
}
func (f *File) Read(buffer []byte) int {
n := copy(buffer, f.data)
return n
}
func (f *File) Write(data []byte) int {
f.data = append(f.data, data...)
return len(data)
}
// 结构体嵌入示例
type Person struct {
Name string
Age int
}
func (p Person) GetInfo() string {
return fmt.Sprintf("%s (%d岁)", p.Name, p.Age)
}
type Employee struct {
Person // 具名嵌入
JobTitle string
Salary float64
}
func (e Employee) GetDetails() string {
return fmt.Sprintf("%s - %s, 薪资: %.0f", e.GetInfo(), e.JobTitle, e.Salary)
}
// 匿名嵌入
type Manager struct {
Person // 匿名嵌入
Department string
TeamSize int
}
func (m Manager) Manage() string {
return fmt.Sprintf("管理 %s团队规模: %d人", m.Department, m.TeamSize)
}
// 方法重写示例
type Student struct {
Person
School string
Grade string
}
// 重写 Person 的 GetInfo 方法
func (s Student) GetInfo() string {
return fmt.Sprintf("%s (%d岁) - %s %s", s.Name, s.Age, s.School, s.Grade)
}// 实际应用
示例
// 银行账户
type BankAccount struct {
AccountNumber string
Balance float64
Owner string
}
func (ba *BankAccount) Deposit(amount float64) {
if amount > 0 {
ba.Balance += amount
fmt.Printf(" 存款 %.2f,当前余额: %.2f\n", amount, ba.Balance)
}
}
func (ba *BankAccount) Withdraw(amount float64) bool {
if amount > 0 && amount <= ba.Balance {
ba.Balance -= amount
fmt.Printf(" 取款 %.2f,当前余额: %.2f\n", amount, ba.Balance)
return true
}
fmt.Printf(" 取款失败:余额不足或金额无效\n")
return false
}
func (ba BankAccount) GetInfo() string {
return fmt.Sprintf("账户: %s, 户主: %s, 余额: %.2f",
ba.AccountNumber, ba.Owner, ba.Balance)
}
// 购物车系统
type CartItem struct {
Name string
Price float64
Quantity int
}
type ShoppingCart struct {
Items []CartItem
}
func (sc *ShoppingCart) AddItem(name string, price float64, quantity int) {
// 检查是否已存在该商品
for i := range sc.Items {
if sc.Items[i].Name == name {
sc.Items[i].Quantity += quantity
return
}
}
// 添加新商品
sc.Items = append(sc.Items, CartItem{
Name: name,
Price: price,
Quantity: quantity,
})
}
func (sc *ShoppingCart) RemoveItem(name string) {
for i, item := range sc.Items {
if item.Name == name {
sc.Items = append(sc.Items[:i], sc.Items[i+1:]...)
return
}
}
}
func (sc ShoppingCart) GetTotal() float64 {
total := 0.0
for _, item := range sc.Items {
total += item.Price * float64(item.Quantity)
}
return total
}
func (sc ShoppingCart) DisplayItems() {
for _, item := range sc.Items {
fmt.Printf(" %s: %.2f × %d = %.2f\n",
item.Name, item.Price, item.Quantity,
item.Price*float64(item.Quantity))
}
}
// 日志记录器
type Logger struct {
Level string
}
func (l *Logger) SetLevel(level string) {
l.Level = level
}
func (l Logger) shouldLog(level string) bool {
levels := map[string]int{
"DEBUG": 0,
"INFO": 1,
"WARN": 2,
"ERROR": 3,
}
currentLevel := levels[l.Level]
messageLevel := levels[level]
return messageLevel >= currentLevel
}
func (l Logger) log(level, message string) {
if l.shouldLog(level) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
fmt.Printf(" [%s] %s: %s\n", timestamp, level, message)
}
}
func (l Logger) Debug(message string) {
l.log("DEBUG", message)
}
func (l Logger) Info(message string) {
l.log("INFO", message)
}
func (l Logger) Warning(message string) {
l.log("WARN", message)
}
func (l Logger) Error(message string) {
l.log("ERROR", message)
}
// 配置管理器
type Config struct {
settings map[string]string
}
func (c *Config) Set(key, value string) {
c.settings[key] = value
}
func (c Config) Get(key string) string {
if value, exists := c.settings[key]; exists {
return value
}
return ""
}
func (c Config) DisplayAll() {
for key, value := range c.settings {
fmt.Printf(" %s = %s\n", key, value)
}
}
// 计算器
type Calculator struct{}
func (calc Calculator) Add(a, b float64) float64 {
return a + b
}
func (calc Calculator) Subtract(a, b float64) float64 {
return a - b
}
func (calc Calculator) Multiply(a, b float64) float64 {
return a * b
}
func (calc Calculator) Divide(a, b float64) float64 {
if b != 0 {
return a / b
}
return 0
}
// 字符串构建器(链式调用)
type StringBuilder struct {
parts []string
}
func NewStringBuilder() *StringBuilder {
return &StringBuilder{parts: make([]string, 0)}
}
func (sb *StringBuilder) Append(str string) *StringBuilder {
sb.parts = append(sb.parts, str)
return sb
}
func (sb *StringBuilder) ToUpper() *StringBuilder {
for i, part := range sb.parts {
sb.parts[i] = strings.ToUpper(part)
}
return sb
}
func (sb *StringBuilder) Build() string {
return strings.Join(sb.parts, "")
}
/*
运行这个程序:
go run 05-methods.go
学习要点:
1. 方法是与特定类型关联的函数
2. 方法定义语法func (receiver Type) MethodName() ReturnType
3. 值接收者和指针接收者有不同的行为和用途
4. 方法集决定了类型可以实现哪些接口
5. 结构体嵌入可以实现方法的继承和组合
方法 vs 函数:
1. 方法有接收者,函数没有
2. 方法属于特定类型,函数是独立的
3. 方法可以访问接收者的字段和其他方法
4. 方法支持多态(通过接口)
接收者类型选择:
1. 值接收者:
- 不需要修改接收者
- 接收者是小的结构体
- 接收者是基本类型、数组或小的结构体
2. 指针接收者:
- 需要修改接收者
- 接收者是大的结构体(避免拷贝)
- 接收者包含不能拷贝的字段(如 sync.Mutex
方法集规则:
1. 值类型 T 的方法集:所有值接收者方法
2. 指针类型 *T 的方法集:所有值接收者和指针接收者方法
3. 接口实现需要考虑方法集的匹配
最佳实践:
1. 保持接收者类型的一致性
2. 优先使用指针接收者(除非有特殊原因)
3. 合理使用结构体嵌入实现代码复用
4. 设计清晰的接口和方法签名
5. 使用方法实现面向对象的设计模式
常见应用场景:
1. 数据封装和操作
2. 业务逻辑实现
3. 接口实现和多态
4. 链式调用和流畅接口
5. 状态管理
6. 配置和选项处理
高级特性:
1. 方法表达式和方法值
2. 接口组合
3. 类型断言
4. 动态方法调用
5. 链式方法调用
*/