first
commit
af01ec1951
|
@ -0,0 +1,8 @@
|
|||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -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>
|
|
@ -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>
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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<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)
|
||||
取到的是小王子 即通过字段名获取对应的值
|
|
@ -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)
|
||||
|
||||
}
|
Loading…
Reference in New Issue