869 lines
20 KiB
Go
869 lines
20 KiB
Go
/*
|
||
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. 链式方法调用
|
||
*/ |