From af01ec19519fa226060e884683eeb84dad440b18 Mon Sep 17 00:00:00 2001 From: Administrator Date: Tue, 2 Jul 2024 18:19:18 +0800 Subject: [PATCH] first --- .idea/.gitignore | 8 +++ .idea/course.iml | 9 +++ .idea/modules.xml | 8 +++ go.mod | 3 + ini_unmarshal/conf_ini.go | 102 +++++++++++++++++++++++++++ ini_unmarshal/config.ini | 18 +++++ kernel-update | 37 ++++++++++ reflector/refelect | 128 ++++++++++++++++++++++++++++++++++ reflector/struct_reflector.go | 46 ++++++++++++ 9 files changed, 359 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/course.iml create mode 100644 .idea/modules.xml create mode 100644 go.mod create mode 100644 ini_unmarshal/conf_ini.go create mode 100644 ini_unmarshal/config.ini create mode 100644 kernel-update create mode 100644 reflector/refelect create mode 100644 reflector/struct_reflector.go diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/course.iml b/.idea/course.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/course.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..94eadf4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8eb04f1 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module course + +go 1.22 diff --git a/ini_unmarshal/conf_ini.go b/ini_unmarshal/conf_ini.go new file mode 100644 index 0000000..b4916ab --- /dev/null +++ b/ini_unmarshal/conf_ini.go @@ -0,0 +1,102 @@ +package main + +import ( + "fmt" + "os" + "strings" + + "reflect" +) + +//定义结构体 + +type MysqlConfig struct { + Address string `ini:"address"` + Port int `ini:"port"` + Username string `ini:"username"` + Password string `ini:"password"` +} + +type RedisConfig struct { + host string `ini:"host"` + Port int `ini:"port"` + Password string `ini:"password"` + Database string `ini:"database"` +} + +type Config struct { + RedisConfig `ini:"mysql"` + MysqlConfig `ini:"redis"` +} + +func Loadini(fileName string, data interface{}) (err error) { + //0.参数的校验,对函数中修改值,必须是结构体指针 + t := reflect.TypeOf(data) + //v := reflect.ValueOf(data) + //校验指针类型 + if t.Kind() != reflect.Ptr { + err = fmt.Errorf("data should be pointer") + return + } + //校验结构体类型,由于是指针,要用elem方法 + if t.Elem().Kind() != reflect.Struct { + err = fmt.Errorf("data should be struct") + return + } + //1.读取文件 + b, err := os.ReadFile(fileName) //读取文件拿到字节类型的数据 + if err != nil { + return + } + + lineSlice := strings.Split(string(b), "\r\n") //字节类型的数据按照换行符切分 + fmt.Printf("%#v\n", lineSlice) + //var structName string + //2.一行一行的读取数据 + for idx, line := range lineSlice { + //2.1如果是注释,就跳过 + line = strings.TrimSpace(line) + if strings.HasPrefix(line, ";") || strings.HasPrefix(line, "#") { + continue + } + //2.2如果是[开头的,就表示节(section) + if strings.HasPrefix(line, "[") { + //校验1 首尾的[]都需要存在 + if line[0] != '[' || line[len(line)-1] != ']' { + err = fmt.Errorf("line:%d syntax error", idx+1) + return + } + //结之间能取到的内容,比如redis或者mysql这个字符串 + sectionName := strings.TrimSpace(line[1 : len(line)-1]) + //校验2 []之间应该有内容 + if len(sectionName) == 0 { //切片:左包含右不包含 + err = fmt.Errorf("line:%d syntax error", idx+1) + return + } + //根据字符串sectionName到data中根据反射找到结构体 + for i := 0; i < t.Elem().NumField(); i++ { + field := t.Elem().Field(i) + if field.Tag.Get("ini") == sectionName { + //找到对应的嵌套结构体 + //structName = field.Name + break + } + } + } else { + //2.3如果不是[,就是=分割的键值对 + } + } + + return // + +} + +func main() { + var cfg Config + err := Loadini("./ini_unmarshal/config.ini", &cfg) + if err != nil { + fmt.Println("load ini error:", err) + return + } + fmt.Println(cfg) +} diff --git a/ini_unmarshal/config.ini b/ini_unmarshal/config.ini new file mode 100644 index 0000000..caa7180 --- /dev/null +++ b/ini_unmarshal/config.ini @@ -0,0 +1,18 @@ +; mysql config +[mysql] +address=1.2.3.4 +port=3306 +username=root +password=pass + + + +# [ +#[ ] +# redis config +[redis] +host=127.0.0.1 +port=6379 +password=root +database=0 + diff --git a/kernel-update b/kernel-update new file mode 100644 index 0000000..2caee2b --- /dev/null +++ b/kernel-update @@ -0,0 +1,37 @@ +#!/bin/bash + + +#查看内核版本 + #$ uname -sr + # + ##系统更新 + #$ yum update + # + ##载入公钥 + #$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org + # + ##安装 ELRepo 最新版本 + #$ yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm + # + ##列出可以使用的 kernel 包版本 + #$ yum list available --disablerepo=* --enablerepo=elrepo-kernel + # + ##安装指定的 kernel 版本:(已查看版本为准,采用lt长期支持版本) + #$ yum install -y kernel-lt-5.4.214-1.el7.elrepo --enablerepo=elrepo-kernel + # + ##查看系统可用内核 + #$ cat /boot/grub2/grub.cfg | grep menuentry + # + ##设置开机从新内核启动 + #$ grub2-set-default "CentOS Linux (5.4.214-1.el7.elrepo.x86_64) 7 (Core)" + # + ##查看内核启动项 + #$ grub2-editenv list + #saved_entry=CentOS Linux (5.4.214-1.el7.elrepo.x86_64) 7 (Core) + # + ##重启系统使内核生效: + #$ reboot + # + ##启动完成查看内核版本是否更新: + #$ uname -r + #5.4.188-1.el7.elrepo.x86_64 \ No newline at end of file diff --git a/reflector/refelect b/reflector/refelect new file mode 100644 index 0000000..cb3a10e --- /dev/null +++ b/reflector/refelect @@ -0,0 +1,128 @@ + 在Go语言中反射的相关功能由内置的reflect包提供,任意接口值在反射中都可以理解为由reflect.Type和reflect.Value两部分组成, + 并且reflect包提供了reflect.TypeOf和reflect.ValueOf两个函数来获取任意对象的Value和Type。 + 1.TypeOf + typeof的对象中可以使用两个方法 t.name t.kind + 其中t.name是自定义命名的名字,而t.kind是底层的类型 + 比如 + type cat struct{} 这个name就是cat 而 kind就是struct + + 2.ValueOf + reflect.ValueOf()返回的是reflect.Value类型,其中包含了原始值的值信息。reflect.Value与原始值之间可以互相转换。 + v对象同样也有kind,但没有name + kind对象可以取到值的类型并转换成对应的原始值 + 例如: + func reflectValue(x interface{}) { + v := reflect.ValueOf(x) + k := v.Kind() + switch k { + case reflect.Int64: + // v.Int()从反射中获取整型的原始值,然后通过int64()强制类型转换 + fmt.Printf("type is int64, value is %d\n", int64(v.Int())) + case reflect.Float32: + // v.Float()从反射中获取浮点型的原始值,然后通过float32()强制类型转换 + fmt.Printf("type is float32, value is %f\n", float32(v.Float())) + case reflect.Float64: + // v.Float()从反射中获取浮点型的原始值,然后通过float64()强制类型转换 + fmt.Printf("type is float64, value is %f\n", float64(v.Float())) + } + } + +通过反射设置变量的值 +想要在函数中通过反射修改变量的值,需要注意函数参数传递的是值拷贝,必须传递变量地址才能修改变量值。而反射中使用专有的Elem()方法来获取指针对应的值。 +比如 +func reflectSetValue1(x interface{}) { + v := reflect.ValueOf(x) + if v.Kind() == reflect.Int64 { + v.SetInt(200) //修改的是副本,reflect包会引发panic + } +} +func reflectSetValue2(x interface{}) { + v := reflect.ValueOf(x) + // 反射中使用 Elem()方法获取指针对应的值 + if v.Elem().Kind() == reflect.Int64 { + v.Elem().SetInt(200) + } +} +func main() { + var a int64 = 100 + // reflectSetValue1(a) //panic: reflect: reflect.Value.SetInt using unaddressable value + reflectSetValue2(&a) //传递a的指针,修改原始值 + fmt.Println(a) +} + +func (v Value) IsNil() bool +报告v持有的值是否为nil。v持有的值的分类必须是通道、函数、接口、映射、指针、切片之一;否则IsNil函数会导致panic。 +func (v Value) IsValid() bool +返回v是否持有一个值。如果v是Value零值会返回假,此时v除了IsValid、String、Kind之外的方法都会导致panic。 + + +func main() { + // *int类型空指针 + var a *int + fmt.Println("var a *int IsNil:", reflect.ValueOf(a).IsNil()) + // nil值 + fmt.Println("nil IsValid:", reflect.ValueOf(nil).IsValid()) + // 实例化一个匿名结构体 + b := struct{}{} + // 尝试从结构体中查找"abc"字段 + fmt.Println("不存在的结构体成员:", reflect.ValueOf(b).FieldByName("abc").IsValid()) + // 尝试从结构体中查找"abc"方法 + fmt.Println("不存在的结构体方法:", reflect.ValueOf(b).MethodByName("abc").IsValid()) + // map + c := map[string]int{} + // 尝试从map中查找一个不存在的键 + fmt.Println("map中不存在的键:", reflect.ValueOf(c).MapIndex(reflect.ValueOf("娜扎")).IsValid()) +} + + +结构体反射 +type student struct { + Name string `json:"name"` + Score int `json:"score"` +} + + +结构体划分为几部分 +stu1 := student{ + Name: "小王子", + Score: 90, +} +比如这个结构体,对typeof这个函数来说返回的对象是t 其中两个方法 是 t.name (student)和 t.kind(struct) +t.NumField()会返回结构体中的字段数目是2 +所以有: +遍历所有结构体字段: +for i:=0;i