Update
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 03-embedding - 组合与类型断言
|
||||
|
||||
## 知识点讲解
|
||||
|
||||
### 结构体嵌入(组合)
|
||||
|
||||
```go
|
||||
type Address struct {
|
||||
City string
|
||||
Street string
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Address Address // 嵌套结构体
|
||||
}
|
||||
|
||||
type Employee struct {
|
||||
Person // 匿名嵌入
|
||||
EmployeeID int
|
||||
}
|
||||
|
||||
emp := Employee{
|
||||
Person: Person{Name: "张三"},
|
||||
}
|
||||
fmt.Println(emp.Name) // 可以直接访问嵌入的字段
|
||||
```
|
||||
|
||||
### 接口嵌入
|
||||
|
||||
```go
|
||||
type Reader interface {
|
||||
Read() string
|
||||
}
|
||||
|
||||
type Writer interface {
|
||||
Write(s string)
|
||||
}
|
||||
|
||||
type ReadWriter interface {
|
||||
Reader
|
||||
Writer // 接口组合
|
||||
}
|
||||
```
|
||||
|
||||
### 类型断言
|
||||
|
||||
```go
|
||||
var i interface{} = "hello"
|
||||
|
||||
// 方式1:标准断言
|
||||
s := i.(string)
|
||||
|
||||
// 方式2:带检查
|
||||
s, ok := i.(string)
|
||||
if !ok {
|
||||
fmt.Println("类型断言失败")
|
||||
}
|
||||
```
|
||||
|
||||
### 类型选择
|
||||
|
||||
```go
|
||||
func printValue(v interface{}) {
|
||||
switch v.(type) {
|
||||
case int:
|
||||
fmt.Println("整数:", v)
|
||||
case string:
|
||||
fmt.Println("字符串:", v)
|
||||
default:
|
||||
fmt.Println("未知类型")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 重要提示
|
||||
|
||||
- Go使用组合而非继承
|
||||
- 结构体嵌入可以实现类似继承的效果
|
||||
- 类型断言若失败会panic,需谨慎使用
|
||||
- 类型选择用于处理多种类型
|
||||
|
||||
## 学习目标
|
||||
|
||||
完成本练习后,你将:
|
||||
- ✅ 掌握结构体嵌入的使用
|
||||
- ✅ 理解接口嵌入的概念
|
||||
- ✅ 学会使用类型断言
|
||||
- ✅ 掌握类型选择的使用
|
||||
|
||||
## 练习说明
|
||||
|
||||
打开 `main.go`,根据注释提示填充代码,完成后运行 `go test -v` 验证答案。
|
||||
@@ -0,0 +1,182 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Address struct {
|
||||
City string
|
||||
Street string
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
Address Address
|
||||
}
|
||||
|
||||
type Employee struct {
|
||||
Person
|
||||
EmployeeID int
|
||||
Department string
|
||||
}
|
||||
|
||||
type Employee2 struct {
|
||||
____
|
||||
Salary float64
|
||||
}
|
||||
|
||||
type Reader interface {
|
||||
Read() string
|
||||
}
|
||||
|
||||
type Writer interface {
|
||||
Write(s string)
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Name string
|
||||
Content string
|
||||
}
|
||||
|
||||
func (f File) Read() string {
|
||||
return f.___
|
||||
}
|
||||
|
||||
func (f *File) Write(s string) {
|
||||
f.Content = ____
|
||||
}
|
||||
|
||||
type ReadWriter interface {
|
||||
____
|
||||
____
|
||||
}
|
||||
|
||||
func exercise1() string {
|
||||
fmt.Println("=== 练习1:结构体嵌入 ===")
|
||||
|
||||
emp := Employee{
|
||||
Person: Person{
|
||||
Name: "张三",
|
||||
Age: 30,
|
||||
},
|
||||
EmployeeID: 1001,
|
||||
Department: "技术部",
|
||||
}
|
||||
|
||||
fmt.Printf("员工姓名: %s, 年龄: %d\n", ____, emp.___)
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise2() string {
|
||||
fmt.Println("=== 练习2:多层嵌入 ===")
|
||||
|
||||
address := Address{City: "北京", Street: "长安街"}
|
||||
|
||||
emp2 := Employee2{
|
||||
Person: Person{
|
||||
Name: "李四",
|
||||
Address: ____,
|
||||
},
|
||||
Salary: 10000.0,
|
||||
}
|
||||
|
||||
fmt.Printf("员工: %s, 城市: %s\n", emp2.___, emp2.___.City)
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise3() string {
|
||||
fmt.Println("=== 练习3:接口实现 ===")
|
||||
|
||||
file := File{Name: "test.txt", Content: "初始内容"}
|
||||
|
||||
// 使用Read方法
|
||||
content := file.____()
|
||||
fmt.Printf("读取内容: %s\n", content)
|
||||
|
||||
// 使用Write方法
|
||||
file.____("新内容")
|
||||
fmt.Printf("写入后内容: %s\n", file.___)
|
||||
|
||||
return ___
|
||||
}
|
||||
|
||||
func exercise4() string {
|
||||
fmt.Println("=== 练习4:接口组合 ===")
|
||||
|
||||
file := &File{Name: "data.txt", "原始数据"}
|
||||
|
||||
var rw _____
|
||||
|
||||
rw.Write("修改后的数据")
|
||||
result := rw.Read()
|
||||
|
||||
fmt.Printf("读写结果: %s\n", result)
|
||||
|
||||
return ____
|
||||
}
|
||||
|
||||
func exercise5() string {
|
||||
fmt.Println("=== 练习5:类型断言 ===")
|
||||
|
||||
var data interface{} = "Hello, Go!"
|
||||
|
||||
// 尝试断言为string
|
||||
str, ok := data.____
|
||||
if ok {
|
||||
fmt.Printf("类型断言成功: %s\n", ____)
|
||||
}
|
||||
|
||||
// 尝试断言为int
|
||||
_, ok = data.____
|
||||
if !ok {
|
||||
fmt.Println("类型断言失败: 不是int类型")
|
||||
}
|
||||
|
||||
return "类型断言演示完成"
|
||||
}
|
||||
|
||||
func exercise6() string {
|
||||
fmt.Println("=== 练习6:类型选择 ===")
|
||||
|
||||
values := []interface{}{10, "hello", 3.14, true}
|
||||
|
||||
for _, v := range ____ {
|
||||
switch v.(type) {
|
||||
case int:
|
||||
fmt.Printf("整数: %d\n", ____)
|
||||
case string:
|
||||
fmt.Printf("字符串: %s\n", ____)
|
||||
case float64:
|
||||
fmt.Printf("浮点数: %.2f\n", ____)
|
||||
case bool:
|
||||
fmt.Printf("布尔值: %t\n", ____)
|
||||
default:
|
||||
fmt.Println("未知类型")
|
||||
}
|
||||
}
|
||||
|
||||
return "类型选择演示完成"
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("=== 组合与类型断言 练习 ===\n")
|
||||
|
||||
result1 := exercise1()
|
||||
fmt.Printf("练习1结果: %s\n", result1)
|
||||
|
||||
result2 := exercise2()
|
||||
fmt.Printf("练习2结果: %s\n", result2)
|
||||
|
||||
result3 := exercise3()
|
||||
fmt.Printf("练习3结果: %s\n", result3)
|
||||
|
||||
result4 := exercise4()
|
||||
fmt.Printf("练习4结果: %s\n", result4)
|
||||
|
||||
result5 := exercise5()
|
||||
fmt.Printf("练习5结果: %s\n", result5)
|
||||
|
||||
result6 := exercise6()
|
||||
fmt.Printf("练习6结果: %s\n", result6)
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
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 != "李四" {
|
||||
t.Errorf("期望 '李四', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise3(t *testing.T) {
|
||||
result := exercise3()
|
||||
if result != "新内容" {
|
||||
t.Errorf("期望 '新内容', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise4(t *testing.T) {
|
||||
result := exercise4()
|
||||
if result != "修改后的数据" {
|
||||
t.Errorf("期望 '修改后的数据', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise5(t *testing.T) {
|
||||
result := exercise5()
|
||||
if result != "类型断言演示完成" {
|
||||
t.Errorf("期望 '类型断言演示完成', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExercise6(t *testing.T) {
|
||||
result := exercise6()
|
||||
if result != "类型选择演示完成" {
|
||||
t.Errorf("期望 '类型选择演示完成', 实际: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMainFunction(t *testing.T) {
|
||||
output := captureOutput(main)
|
||||
|
||||
requiredSections := []string{
|
||||
"=== 组合与类型断言 练习 ===",
|
||||
"练习1:结构体嵌入",
|
||||
"练习2:多层嵌入",
|
||||
"练习3:接口实现",
|
||||
"练习4:接口组合",
|
||||
"练习5:类型断言",
|
||||
"练习6:类型选择",
|
||||
}
|
||||
|
||||
for _, section := range requiredSections {
|
||||
if !strings.Contains(output, section) {
|
||||
t.Errorf("期望输出包含 '%s'", section)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user