main
Administrator 2024-07-02 18:19:18 +08:00
commit af01ec1951
9 changed files with 359 additions and 0 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

9
.idea/course.iml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/course.iml" filepath="$PROJECT_DIR$/.idea/course.iml" />
</modules>
</component>
</project>

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module course
go 1.22

102
ini_unmarshal/conf_ini.go Normal file
View File

@ -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)
}

18
ini_unmarshal/config.ini Normal file
View File

@ -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

37
kernel-update Normal file
View File

@ -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

128
reflector/refelect Normal file
View File

@ -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.kindstruct
t.NumField()会返回结构体中的字段数目是2
所以有:
遍历所有结构体字段:
for i:=0;i<t.NumField();i++{
field:=t.field(i)
fmt.Printf("name:%s index:%d type:%v json tag:%v\n", field.Name, field.Index, field.Type, field.Tag.Get("json"))
}
对结构体来说t这个对象的返回值中存在以下类型通过t.field(索引)获取:
type StructField struct {
// Name是字段的名字。PkgPath是非导出字段的包路径对导出字段该字段为""。
// 参见http://golang.org/ref/spec#Uniqueness_of_identifiers
Name string
PkgPath string
Type Type // 字段的类型
Tag StructTag // 字段的标签
Offset uintptr // 字段在结构体中的字节偏移量
Index []int // 用于Type.FieldByIndex时的索引切片
Anonymous bool // 是否匿名字段
}
比如当第一次循环时StructField中能找到的信息是
Name : Name
PkgPath : ""
Type :string
Tag : json“name”
offset: 0
index: [0]
Anonymous:false
同时t对象还可以通过方法FieldByName去找到对应的字段
比如
if scoreField, ok := t.FieldByName("Score"); ok {
fmt.Printf("name:%s index:%d type:%v json tag:%v\n", scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
}
返回的就是结构体中第二个字段的信息
v对象也有FieldByName找到的是对应字段的值信息
比如
wangzi := v.FieldByName("Name")
fmt.Println(wangzi)
取到的是小王子 即通过字段名获取对应的值

View File

@ -0,0 +1,46 @@
package main
import (
"fmt"
"reflect"
)
type student struct {
Name string `json:"name"`
Score int `json:"score"`
}
var stu1 = student{
Name: "小王子",
Score: 90,
}
func main() {
t := reflect.TypeOf(stu1)
fmt.Println(t.Name(), t.Kind()) // student struct
fmt.Println(t.NumField()) //2
// 通过for循环遍历结构体的所有字段信息
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fmt.Println(field)
fmt.Printf("name:%s index:%d type:%v json tag:%v\n", field.Name, field.Index, field.Type, field.Tag.Get("json"))
}
// 通过字段名获取指定结构体字段信息
if scoreField, ok := t.FieldByName("Score"); ok {
fmt.Printf("name:%s index:%d type:%v json tag:%v\n", scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
}
fmt.Println("======================ValueOf==================")
v := reflect.ValueOf(stu1)
fmt.Println(v.NumField()) //2
for i := 0; i < v.NumField(); i++ {
field2 := v.Field(i)
fmt.Println(field2)
} //遍历值
wangzi := v.FieldByName("Name")
fmt.Println(wangzi)
}