Update
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# 02-methods - 方法定义
|
||||
|
||||
## 知识点讲解
|
||||
|
||||
### 方法定义
|
||||
|
||||
```go
|
||||
// 值接收者
|
||||
func (p Person) GetName() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
// 指针接收者
|
||||
func (p *Person) SetName(name string) {
|
||||
p.Name = name
|
||||
}
|
||||
```
|
||||
|
||||
### 值接收者 vs 指针接收者
|
||||
|
||||
```go
|
||||
type Counter struct {
|
||||
value int
|
||||
}
|
||||
|
||||
func (c Counter) GetValue() int {
|
||||
return c.value // 只读,不修改原值
|
||||
}
|
||||
|
||||
func (c *Counter) Increment() {
|
||||
c.value++ // 值读写,修改原值
|
||||
}
|
||||
```
|
||||
|
||||
### 方法选择
|
||||
|
||||
| 场景 | 接收者类型 |
|
||||
|------|-----------|
|
||||
| 方法不需要修改接收者 | 值接收者 |
|
||||
| 方法需要修改接收者 | 指针接收者 |
|
||||
| 接收者较大,避免拷贝 | 指针接收者 |
|
||||
| 保持接口兼容性 | 值接收者 |
|
||||
|
||||
### 方法表达式与值
|
||||
|
||||
```go
|
||||
c := Counter{value: 10}
|
||||
|
||||
// 方法调用
|
||||
c.Increment()
|
||||
|
||||
// 方法表达式
|
||||
f := (*Counter).Increment
|
||||
f(&c)
|
||||
```
|
||||
|
||||
### 重要提示
|
||||
|
||||
- 值接收者可以用于指针类型,反之则需要Go自动转换
|
||||
- 方法集规则影响接口实现
|
||||
- 选择接收者类型要考虑一致性
|
||||
|
||||
## 学习目标
|
||||
|
||||
完成本练习后,你将:
|
||||
- ✅ 掌握方法的定义方式
|
||||
- ✅ 理解值接收者和指针接收者的区别
|
||||
- ✅ 学会为结构体定义方法
|
||||
- ✅ 掌握方法的选择原则
|
||||
|
||||
## 练习说明
|
||||
|
||||
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
|
||||
@@ -0,0 +1,163 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Email string
|
||||
}
|
||||
|
||||
func (p Person) GetName() string {
|
||||
return ____
|
||||
}
|
||||
|
||||
func (p Person) GetAge() int {
|
||||
return ____
|
||||
}
|
||||
|
||||
func (p *Person) SetName(name string) {
|
||||
____ = ____
|
||||
}
|
||||
|
||||
func (p *Person) SetEmail(email string) {
|
||||
____ = ____
|
||||
}
|
||||
|
||||
func (p Person) GetInfo() string {
|
||||
return fmt.Sprintf("%s, %d岁, %s", ____, ____, ____)
|
||||
}
|
||||
|
||||
type Rectangle struct {
|
||||
Width float64
|
||||
Height float64
|
||||
}
|
||||
|
||||
func (r Rectangle) Area() float64 {
|
||||
return ____
|
||||
}
|
||||
|
||||
func (r *Rectangle) Resize(width, height float64) {
|
||||
____ = ____
|
||||
____ = ____
|
||||
}
|
||||
|
||||
type BankAccount struct {
|
||||
Balance float64
|
||||
Owner string
|
||||
}
|
||||
|
||||
func (b *BankAccount) Deposit(amount float64) {
|
||||
b.Balance += ____
|
||||
}
|
||||
|
||||
func (b *BankAccount) Withdraw(amount float64) bool {
|
||||
if b.Balance >= amount {
|
||||
b.Balance -= ____
|
||||
return ____
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b BankAccount) GetBalance() float64 {
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise1() string {
|
||||
fmt.Println("=== 练习1:基础方法 ===")
|
||||
|
||||
person := Person{Name: "张三", Age: 25, Email: "zhangsan@example.com"}
|
||||
|
||||
name := ____
|
||||
age := ____
|
||||
|
||||
person.SetName(____)
|
||||
person.SetEmail(____)
|
||||
|
||||
fmt.Printf("姓名: %s, 年龄: %d\n", ____, person.Age)
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise2() float64 {
|
||||
fmt.Println("=== 练习2:矩形方法 ===")
|
||||
|
||||
rect := Rectangle{Width: 10, Height: 5}
|
||||
|
||||
area := ____
|
||||
|
||||
fmt.Printf("矩形面积: %.2f\n", area)
|
||||
|
||||
rect.Resize(____, ____)
|
||||
|
||||
newArea := ____
|
||||
fmt.Printf("调整后面积: %.2f\n", ____)
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise3() float64 {
|
||||
fmt.Println("=== 练习3:银行账户方法 ===")
|
||||
|
||||
account := BankAccount{Balance: 1000, Owner: "张三"}
|
||||
|
||||
account.____(500)
|
||||
fmt.Printf("存款后余额: %.2f\n", account.____())
|
||||
|
||||
success := account.____(300)
|
||||
if success {
|
||||
fmt.Printf("取款成功,余额: %.2f\n", account.____())
|
||||
}
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise4() string {
|
||||
fmt.Println("=== 练习4:方法链 ===")
|
||||
|
||||
// 使用方法链调用
|
||||
person := Person{Name: "李四", Age: 30, Email: "lisi@example.com"}
|
||||
|
||||
person.SetName("李四(更新)").SetEmail("lisi_new@example.com")
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise5() int {
|
||||
fmt.Println("=== 练习5:计算器方法 ===")
|
||||
|
||||
type Calculator struct {
|
||||
value int
|
||||
}
|
||||
|
||||
calc := Calculator{value: 0}
|
||||
|
||||
calc.setValue := func(v int) {
|
||||
calc.value = v
|
||||
}
|
||||
|
||||
calc.setValue(10)
|
||||
|
||||
fmt.Printf("计算器值: %d\n", calc.value)
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("=== 方法 练习 ===\n")
|
||||
|
||||
result1 := exercise1()
|
||||
fmt.Printf("练习1结果: %s\n", result1)
|
||||
|
||||
result2 := exercise2()
|
||||
fmt.Printf("练习2结果: %.2f\n", result2)
|
||||
|
||||
result3 := exercise3()
|
||||
fmt.Printf("练习3结果: %.2f\n", result3)
|
||||
|
||||
result4 := exercise4()
|
||||
fmt.Printf("练习4结果: %s\n", result4)
|
||||
|
||||
result5 := exercise5()
|
||||
fmt.Printf("练习5结果: %d\n", result5)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func captureOutput(f func()) string {
|
||||
old := os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
f()
|
||||
|
||||
w.Close()
|
||||
os.Stdout = old
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.ReadFrom(r)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func TestExercise1(t *testing.T) {
|
||||
result := exercise1()
|
||||
if result != "张三(更新)" {
|
||||
t.Errorf("期望 '张三(更新)', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise2(t *testing.T) {
|
||||
result := exercise2()
|
||||
if result != 80 {
|
||||
t.Errorf("期望 80, 实际: %f", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise3(t *testing.T) {
|
||||
result := exercise3()
|
||||
if result != 1200 {
|
||||
t.Errorf("期望 1200, 实际: %f", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise4(t *testing.T) {
|
||||
result := exercise4()
|
||||
if result != "李四(更新)" {
|
||||
t.Errorf("期望 '李四(更新)', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise5(t *testing.T) {
|
||||
result := exercise5()
|
||||
if result != 10 {
|
||||
t.Errorf("期望 10, 实际: %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMainFunction(t *testing.T) {
|
||||
output := captureOutput(main)
|
||||
|
||||
requiredSections := []string{
|
||||
"=== 方法 练习 ===",
|
||||
"练习1:基础方法",
|
||||
"练习2:矩形方法",
|
||||
"练习3:银行账户方法",
|
||||
"练习4:方法链",
|
||||
"练习5:计算器方法",
|
||||
}
|
||||
|
||||
for _, section := range requiredSections {
|
||||
if !strings.Contains(output, section) {
|
||||
t.Errorf("期望输出包含 '%s'", section)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user