diff --git a/day04/README.md b/day04/README.md index 378de00..4eaed32 100644 --- a/day04/README.md +++ b/day04/README.md @@ -1,5 +1,5 @@ # 结构体(2)与指针 + [Go语言结构体](./struct/README.md) -+ Go语言指针 -+ 扩展反射与内存对齐 \ No newline at end of file ++ [Go语言指针】【](./pointer/README.md) ++ [扩展: Go语言反射](./reflect/README.md) \ No newline at end of file diff --git a/day04/pointer/README.md b/day04/pointer/README.md new file mode 100644 index 0000000..a114734 --- /dev/null +++ b/day04/pointer/README.md @@ -0,0 +1,16 @@ +# 指针 + +## 陷阱 2:指针指向栈变量的地址逃逸 +Go 编译器会自动处理,通常无需担心: + +```go +func getPtr() *int { + v := 10 + return &v // v 虽然是局部变量,但 Go 会自动提升到堆 +} + +``` + +![alt text](image.png) + +## 作业: 实现链表节点和基本操作 \ No newline at end of file diff --git a/day04/pointer/image.png b/day04/pointer/image.png new file mode 100644 index 0000000..f17a159 Binary files /dev/null and b/day04/pointer/image.png differ diff --git a/day04/pointer/link_list.drawio b/day04/pointer/link_list.drawio new file mode 100644 index 0000000..b2aaa0b --- /dev/null +++ b/day04/pointer/link_list.drawio @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/day04/reflect/README.md b/day04/reflect/README.md new file mode 100644 index 0000000..0ecb2af --- /dev/null +++ b/day04/reflect/README.md @@ -0,0 +1,110 @@ +# 反射与内存对齐(扩展) + + + +## 反射获取值与类型 + +```go +// obj -> []byte 类型是 any +func JsonEncode(obj any) []byte { + // 反射获取类型信息 + ot := reflect.TypeOf(obj) + fmt.Println("类型名称:", ot.Name()) + fmt.Println("类型种类:", ot.Kind()) + // 类型名称: TranficTool + // 类型种类: struct + + // 反射获取值信息 + ov := reflect.ValueOf(obj) + fmt.Println("值:", ov) + // 值: {自行车 20 黑色} + + return []byte{} +} +``` + +## 反射获取stuct的字段和 Struct Tag + +```go +// obj -> []byte 类型是 any +func JsonEncode(obj any) []byte { + // 反射获取类型信息 + ot := reflect.TypeOf(obj) + fmt.Println("类型名称:", ot.Name()) + fmt.Println("类型种类:", ot.Kind()) + // 类型名称: TranficTool + // 类型种类: struct + + // 反射获取值信息 + ov := reflect.ValueOf(obj) + fmt.Println("值:", ov) + // 反射获取结构体字段信息(TranficTool) + for i := 0; i < ot.NumField(); i++ { + field := ot.Field(i) + fieldValue := ov.Field(i) + fmt.Printf(" 字段 %d: 名称=%s, 类型=%s, Tag=%s, JsonTag=%s, Value=%v\n", + i, field.Name, field.Type.Name(), field.Tag, field.Tag.Get("json"), fieldValue.Interface()) + } + + // 类型名称: TranficTool + // 类型种类: struct + // 值: {自行车 20 黑色} + // 字段 0: 名称=Name, 类型=string, Tag=json:"name", JsonTag=name, Value=自行车 + // 字段 1: 名称=Speed, 类型=int, Tag=json:"speed", JsonTag=speed, Value=20 + // 字段 2: 名称=Color, 类型=string, Tag=json:"color", JsonTag=color, Value=黑色 + // + // 很容易就可以构建出 Json 数据 + // {"name":"自行车","speed":20,"color":"黑色"} + + return []byte{} +} +``` + + +## 动态修改对象 + +```go +// obj -> []byte 类型是 any +func JsonEncode(obj any) []byte { + // 反射获取类型信息 + ot := reflect.TypeOf(obj) + + if ot.Kind() != reflect.Pointer && ot.Kind() != reflect.Struct { + panic("必须是结构体指针类型") + } + + ot = ot.Elem() // 获取指针指向的类型 + + fmt.Println("类型名称:", ot.Name()) + fmt.Println("类型种类:", ot.Kind()) + // 类型名称: TranficTool + // 类型种类: struct + + // 反射获取值信息 + ov := reflect.ValueOf(obj).Elem() + fmt.Println("值:", ov) + // 反射获取结构体字段信息(TranficTool) + for i := 0; i < ot.NumField(); i++ { + field := ot.Field(i) + fieldValue := ov.Field(i) + if field.Name == "Name" { + fmt.Println("发现 Name 字段,准备进行特殊处理...") + fieldValue.SetString(fieldValue.String() + "_changed") + } + fmt.Printf(" 字段 %d: 名称=%s, 类型=%s, Tag=%s, JsonTag=%s, Value=%v\n", + i, field.Name, field.Type.Name(), field.Tag, field.Tag.Get("json"), fieldValue.Interface()) + } + + // 类型名称: TranficTool + // 类型种类: struct + // 值: {自行车 20 黑色} + // 字段 0: 名称=Name, 类型=string, Tag=json:"name", JsonTag=name, Value=自行车 + // 字段 1: 名称=Speed, 类型=int, Tag=json:"speed", JsonTag=speed, Value=20 + // 字段 2: 名称=Color, 类型=string, Tag=json:"color", JsonTag=color, Value=黑色 + // + // 很容易就可以构建出 Json 数据 + // {"name":"自行车","speed":20,"color":"黑色"} + + return []byte{} +} +``` \ No newline at end of file diff --git a/day04/reflect/main.go b/day04/reflect/main.go new file mode 100644 index 0000000..151e1a4 --- /dev/null +++ b/day04/reflect/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "fmt" + "reflect" +) + +func main() { + // bike 对象 + bike := TranficTool{Name: "自行车", Speed: 20, Color: "黑色"} + JsonEncode(&bike) + fmt.Println(bike) +} + +// obj -> []byte 类型是 any +func JsonEncode(obj any) []byte { + // 反射获取类型信息 + ot := reflect.TypeOf(obj) + + if ot.Kind() != reflect.Pointer && ot.Kind() != reflect.Struct { + panic("必须是结构体指针类型") + } + + ot = ot.Elem() // 获取指针指向的类型 + + fmt.Println("类型名称:", ot.Name()) + fmt.Println("类型种类:", ot.Kind()) + // 类型名称: TranficTool + // 类型种类: struct + + // 反射获取值信息 + ov := reflect.ValueOf(obj).Elem() + fmt.Println("值:", ov) + // 反射获取结构体字段信息(TranficTool) + for i := 0; i < ot.NumField(); i++ { + field := ot.Field(i) + fieldValue := ov.Field(i) + if field.Name == "Name" { + fmt.Println("发现 Name 字段,准备进行特殊处理...") + fieldValue.SetString(fieldValue.String() + "_changed") + } + fmt.Printf(" 字段 %d: 名称=%s, 类型=%s, Tag=%s, JsonTag=%s, Value=%v\n", + i, field.Name, field.Type.Name(), field.Tag, field.Tag.Get("json"), fieldValue.Interface()) + } + + // 类型名称: TranficTool + // 类型种类: struct + // 值: {自行车 20 黑色} + // 字段 0: 名称=Name, 类型=string, Tag=json:"name", JsonTag=name, Value=自行车 + // 字段 1: 名称=Speed, 类型=int, Tag=json:"speed", JsonTag=speed, Value=20 + // 字段 2: 名称=Color, 类型=string, Tag=json:"color", JsonTag=color, Value=黑色 + // + // 很容易就可以构建出 Json 数据 + // {"name":"自行车","speed":20,"color":"黑色"} + + return []byte{} +} + +type TranficTool struct { + // `` 表示字符串 都是 Struct Tag, 结构体标签,lib 反射使用 + Name string `json:"name"` + Speed int `json:"speed"` + Color string `json:"color"` +} diff --git a/day04/struct/json.drawio b/day04/struct/json.drawio index affe2cd..4094c55 100644 --- a/day04/struct/json.drawio +++ b/day04/struct/json.drawio @@ -1,6 +1,6 @@ - + @@ -70,6 +70,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +