2024年08月06日
《圣经》是亚伯拉罕诸教的宗教经典,它不仅仅只是一本宗教读物,其中融合着历史、文化、政治、经济。其中的《圣经故事》反映了犹太民族的形成发展,赞颂了犹太人民的智慧与创造力,至今仍有极高的阅读价值。它与希腊文明一起,形成了今天的欧美文化。下面是
2024年08月06日
主播荐一荐:推荐优质“新”主播~
在这个流量为王的时代,不管是网红、明星还是主播,终究逃不过需要流量傍身的结果,流量就意味着人气,也意味着更可观的收入。对于直播圈来说,想提升人气有多种方式,比如几句广为流传的流行语,大司马就是凭这一点迅速蹿红。亦或者自带有趣的梗,比如下面这一位,可能不知道他的名字,但他全身都是梗。
2024年08月06日
go get github.com/pythonsite/config_yaml
直接上代码:
// 可以用于处理读yaml格式的配置文件,同时也可以用于理解golang中的反射
package config_yaml
import (
"strings"
"errors"
"io/ioutil"
"gopkg.in/yaml.v2"
"reflect"
"fmt"
"strconv"
)
type ConfigEngine struct {
data map[interface{}]interface{}
}
// 将ymal文件中的内容进行加载
func (c *ConfigEngine) Load (path string) error {
ext := c.guessFileType(path)
if ext == "" {
return errors.New("cant not load" + path + " config")
}
return c.loadFromYaml(path)
}
//判断配置文件名是否为yaml格式
func (c *ConfigEngine) guessFileType(path string) string {
s := strings.Split(path,".")
ext := s[len(s) - 1]
switch ext {
case "yaml","yml":
return "yaml"
}
return ""
}
// 将配置yaml文件中的进行加载
func (c *ConfigEngine) loadFromYaml(path string) error {
yamlS,readErr := ioutil.ReadFile(path)
if readErr != nil {
return readErr
}
// yaml解析的时候c.data如果没有被初始化,会自动为你做初始化
err := yaml.Unmarshal(yamlS, &c.data)
if err != nil {
return errors.New("can not parse "+ path + " config" )
}
return nil
}
// 从配置文件中获取值
func (c *ConfigEngine) Get(name string) interface{}{
path := strings.Split(name,".")
data := c.data
for key, value := range path {
v, ok := data[value]
if !ok {
break
}
if (key + 1) == len(path) {
return v
}
if reflect.TypeOf(v).String() == "map[interface {}]interface {}"{
data = v.(map[interface {}]interface {})
}
}
return nil
}
// 从配置文件中获取string类型的值
func (c *ConfigEngine) GetString(name string) string {
value := c.Get(name)
switch value:=value.(type){
case string:
return value
case bool,float64,int:
return fmt.Sprint(value)
default:
return ""
}
}
// 从配置文件中获取int类型的值
func (c *ConfigEngine) GetInt(name string) int {
value := c.Get(name)
switch value := value.(type){
case string:
i,_:= strconv.Atoi(value)
return i
case int:
return value
case bool:
if value{
return 1
}
return 0
case float64:
return int(value)
default:
return 0
}
}
// 从配置文件中获取bool类型的值
func (c *ConfigEngine) GetBool(name string) bool {
value := c.Get(name)
switch value := value.(type){
case string:
str,_:= strconv.ParseBool(value)
return str
case int:
if value != 0 {
return true
}
return false
case bool:
return value
case float64:
if value != 0.0 {
return true
}
return false
default:
return false
}
}
// 从配置文件中获取Float64类型的值
func (c *ConfigEngine) GetFloat64(name string) float64 {
value := c.Get(name)
switch value := value.(type){
case string:
str,_ := strconv.ParseFloat(value,64)
return str
case int:
return float64(value)
case bool:
if value {
return float64(1)
}
return float64(0)
case float64:
return value
default:
return float64(0)
}
}
// 从配置文件中获取Struct类型的值,这里的struct是你自己定义的根据配置文件
func (c *ConfigEngine) GetStruct(name string,s interface{}) interface{}{
d := c.Get(name)
switch d.(type){
case string:
c.setField(s,name,d)
case map[interface{}]interface{}:
c.mapToStruct(d.(map[interface{}]interface{}), s)
}
return s
}
func (c *ConfigEngine) mapToStruct(m map[interface{}]interface{},s interface{}) interface{}{
for key, value := range m {
switch key.(type) {
case string:
c.setField(s,key.(string),value)
}
}
return s
}
// 这部分代码是重点,需要多看看
func (c *ConfigEngine) setField(obj interface{},name string,value interface{}) error {
// reflect.Indirect 返回value对应的值
structValue := reflect.Indirect(reflect.ValueOf(obj))
structFieldValue := structValue.FieldByName(name)
// isValid 显示的测试一个空指针
if !structFieldValue.IsValid() {
return fmt.Errorf("No such field: %s in obj",name)
}
// CanSet判断值是否可以被更改
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", name)
}
// 获取要更改值的类型
structFieldType := structFieldValue.Type()
val := reflect.ValueOf(value)
if structFieldType.Kind() == reflect.Struct && val.Kind() == reflect.Map {
vint := val.Interface()
switch vint.(type) {
case map[interface{}]interface{}:
for key, value := range vint.(map[interface{}]interface{}) {
c.setField(structFieldValue.Addr().Interface(), key.(string), value)
}
case map[string]interface{}:
for key, value := range vint.(map[string]interface{}) {
c.setField(structFieldValue.Addr().Interface(), key, value)
}
}
} else {
if structFieldType != val.Type() {
return errors.New("Provided value type didn't match obj field type")
}
structFieldValue.Set(val)
}
return nil
}
2024年08月06日
本文利用到的 Go 语言相关技术:
2024年08月06日
来自:开发者热榜 开发者头条
本书涵盖 CGO、Go 汇编语言、RPC 实现、Web 框架实现、分布式系统等高阶主题,针对 Go 语言有一定经验想深入了解 Go 语言各种高级用法的开发人员。
对于刚学习 Go 语言的读者,建议先从《Go 语言圣经》开始系统学习 Go 语言的基础知识。如果希望了解 Go2 的最新动向,可以参考《Go2 编程指南》。
2024年08月06日
优质文章,第一时间送达!
本周分享的是几本 Python 进阶书,以及热门编程语言 Go 的两本入门书籍。觉得不错的,请多分享哦~
1、流畅的 Python
口碑特别好的一本 Python 进阶书籍,没有看过的同学别错过了哦~之前分享过一篇介绍本书具体内容的文章,《流畅的 Python》到底好在哪?
2024年08月06日
文章参考go语言圣经,并进行了整理,希望可以帮到工作中有需要的小伙伴~
在一个线性(只有一个goroutine)程序中,程序的执行顺序由程序的逻辑来决定。在有两个或者更多goroutine的程序中,每一个goroutine内的语句也是按照顺序去执行的,但是没法知道不同goroutine中事件的执行顺序,当无法确认一个事件是在另一个事件前面或后面发生的时候,说明这些事件是并发的