Golang关键字defer 作者: lovingyu_er 时间: 2020-07-26 19:05:06 分类: Golang 评论 ```defer``` 和 ```go``` 一样,都是Go语言提供的关键字 ```defer``` 用于资源的释放,会在函数返回值之前进行调用和执行,和析构函数功能类似。**函数返回值以前**这里会有许多细节要注意: defer是在return之前执行,但是return 语句并不是一个原子语句,也就是说它会分赋值和ret指令两部分。 ####多个defer的执行顺序 代码如下: ``` //defer 多个defer调用 //越后面的越被优先调用 func f5()(result int){ result = 99 defer func(){ fmt.Println("func one ") }() defer func(){ fmt.Println("func two") }() defer func(){ fmt.Println("func three") }() return } ``` 输出结果: ``` func three func two func one ``` 可以看到,对于```defer```定义的函数,越靠后越优先执行. ####defer使用场景 1. defer传址调用: ``` //defer传址调用 func f4()(result int){ result = 10 defer func(param *int){ *param = *param+99 }(&result) return } ``` 返回结果,当然是109啦,传址调用比较好理解,传送的是变量的内存地址,当在defer修改的时候,自然就会修改原变量的值。 2. defer传值调用: 案例: ``` //defer中传递参数 func f3() (result int){ result = 9 defer func( pararm int){ pararm = pararm+5 }(result) return result } ``` 传值调用,和普通的函数调用差不多,相当于defer中虽然执行了代码,但是 ```result``` 的参数并没有改变。 上述都是一些传参数的时候,代码执行的时候,```defer``` 没有参数的情况,一些变量的作用域就要考虑一下了。 函数的返回是:先对返回值进行赋值,然后调用defer定义的函数,最后才返回到调用函数里面。 案例: ``` func fff()(result int){ defer func(){ result ++ }() //定义并执行 return } ``` 结果返回为```1``` 代码可以修改为如下: ``` func fff()(result int){ result = 0 defer func(){ result ++ }() //定义并执行 return result } ``` result 在这里算是函数作用域里的变量,所以在defer定义的函数里面也是有效? 案例: 源代码 ``` func f1() (r int){ t :=2 defer func(){ t=t+99 }() return } ``` 返回的结果是0 注意,在Go语言的声明变量中,会自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值。 1. 整型和浮点型变量的默认值为0和0.0 2. 字符串变量的默认值为空字符串 3. 布尔型变量默认为bool 4. 切片,函数,指针变量的默认为nil 注意拿小本本记住啦.. ####场景 1. 在函数返回数据以前,需要检查返回的数据是否符合规则,不规则的可以通过defer进行修正.
Nginx搭建负载均衡 作者: lovingyu_er 时间: 2020-07-08 14:29:00 分类: 架构学习笔记, 技术品鉴,朝花夕拾 评论 ####负载均衡 关于负载均衡的定义,是一个比较好理解的概念,比较像小时候提水一样,一个人提会很累,再找一个人分担,两个人都会相对比较轻松一样,说白了就是分担了重量,负载均衡在这里就是相对来说就是分担流量,从而解决了单个节点压力过大,造成Web服务响应过慢的问题,避免了严重情况下导致服务瘫痪,而导致服务不能正常服务的问题。对于用户来说,如果你后台服务器挂掉一个,而仍能够正常访问,用户无感知,再加上```keepalived```,就可以自动剔除无效的web节点 ####搭建: ######1. 服务器准备: ``` 负载均衡服务器:172.31.56.229 web服务器1:172.31.56.228 web服务器2:172.31.56.230 ``` ######2. 安装nginx 三台服务器上全部安装服务器 ######3. 服务器配置: 负载均衡服务器配置(```172.31.56.229```) ``` upstream serverlist { server 172.31.56.230:8383 weight=1; server 172.31.56.228:8383 weight=1; } server { listen 80; server_name your.domain.com; location / { proxy_pass http://serverlist; } } ``` web服务器1的nginx配置(```172.31.56.228```): ``` server { listen 8383; root /home/darrykinger/test_slb/; # Add index.php to the list if you are using PHP index index.html index.php server_name serverlist; } ``` web服务器2的nginx配置(```172.31.56.230```): ``` server { listen 8383; root /home/ubuntu/test_slb/; index index.html index.htm index.nginx-debian.html; server_name serverlist; } ``` 每个主机,配置好以后,请```reload```一下```nginx```服务,访问你的域名就可以了,比如使用```curl```或者浏览器访问你的域名,注意:上述的**负载均衡服务器**的那台服务器,有一个公网IP地址,我配置了域名,用域名就可以直接访问了。这个案例只是个人实验,生产环境还要增加很多的安全限制。 注意:负载均衡是负载均衡,高可用是高可用,是两个独立的概念,前者是分流,后者是提供不间断的服务。
PHP 金融计算相关的函数之bcsub 作者: lovingyu_er 时间: 2020-07-07 16:48:00 分类: 编程语言,PHP,朝花夕拾 评论 ####bcsub 作用: 2个任意精度数字的减法 由于PHP是一种弱类型预言,但是其在底层的实现上,是基于C来实现的。想要处理数据的精度的问题上,我们就不能单纯的使用基本的类型了,我们要引入php的扩展```bcmath```,在框架中,一般都支持对此系列函数的支持。 ####bcsub案例:两个任意精度的操作数相减 ``` var_dump(bcsub('yes','no') === '0'); ``` 输出结果: ``` bool(true) ``` ####bccomp()函数:比较两个任意精度的数字: ``` bccomp ( string $left_operand , string $right_operand [, int $scale = int ] ) : int ``` 如果```$left_operand```大于```$right_operand```,就会返回1,如果小于就会返回-1,相等返回0 ####bcadd()函数:两个任意精度的数组相加 案例: ``` $exp1 = "1E5"; $exp2 = "2E4"; $ans1 = bcadd((float)$exp1, (float)$exp2, 3); $ans2 = bcadd((int)$exp1, (int)$exp2, 3); $ans3 = bcadd($exp1, $exp2, 3); echo "1: $exp1 + $exp2 = $ans1\r\n"; echo "2: $exp1 + $exp2 = $ans2\r\n"; echo "3: $exp1 + $exp2 = $ans3\r\n"; 1: 1E5 + 2E4 = 120000.000 2: 1E5 + 2E4 = 3.000 3: 1E5 + 2E4 = 0.000 ``` 注意:"1E5"默认的是字符串,如果想要转换成科学计数,需要使用float实现强制类型转换。 ####bcdiv()函数:两个任意精度的数字除法运算 ``` bcdiv ( string $left_operand , string $right_operand [, int $scale = int ] ) : string ``` 解释:左操作数除于右操作数 案例: ```
PHP函数之compact的用法 作者: lovingyu_er 时间: 2020-07-07 11:47:38 分类: 朝花夕拾 评论 PHP函数的compact的作用: 建立一个数组,包括变量名和他们的值 ``` compact (mixed $varname1 ,mixed $varnam2....) ``` 在我开发的微信商城中,经常使用: ``` public function make(int $status, string $msg, ?array $data = null): Response { $res = compact('status', 'msg'); if (!is_null($data)) $res['data'] = $data; return Response::create($res, 'json', $this->code); } public function fail($msg = 'fail', ?array $data = null): Response { if (is_array($msg)) { $data = $msg; $msg = 'ok'; } return $this->make(400, $msg, $data); } ``` 这个是```Json.php```的选段, 创建一个包含变量与其值的数组。 ```compact()``` 会将"status"键名自动和$status参数做键值的关联。"msg"和传递的变量$msg做关联,compact定义的在外部没有的, 官方给出的一个demo: ``` $city = "San Francisco"; $state = "CA"; $event = "SIGGRAPH"; $location_vars = array("city", "state"); $result = compact("event", "nothing_here", $location_vars); print_r($result); ``` 注意: **因为可变变量也许不能在函数内部用于 PHP 的超全局数组,此时不能将超全局数组传递入 compact() 中。** 下面的案例: ``` $arr = explode(' ', 'count acw cols coldepth'); print_r($arr); //$arr = array_flip($arr); print_r($arr); $test ="a"; $count = 999; $new_arr = compact("test",$arr); print_r($new_arr); ``` 对于案例中的$arr的结果: ``` Array ( [0] => count [1] => acw [2] => cols [3] => coldepth ) ``` 对于在外部没有定义的```acw```,```cols```,```coldepth```,php会爆出PHP Notice 的提示。 看下面的案例,对于compact中的字符串中,如果上文定义了一个数组,会有什么效果呢? ``` $city = "San Francisco"; $state = "CA"; $event = "SIGGRAPH"; $location_vars = array("city", "state"); $nothing_here = "yeah ,Nothings "; $result = compact("event", "nothing_here", "location_vars"); print_r($result); ``` 输出结果如下: ``` Array ( [event] => SIGGRAPH [nothing_here] => yeah ,Nothings [location_vars] => Array ( [0] => city [1] => state ) ) ```
Golang 调试出现:2020/07/06 01:15:11 http: panic serving [::1]:51961: runtime error: invalid memory address or nil pointer dereference 作者: lovingyu_er 时间: 2020-07-06 01:25:00 分类: 编程语言,Golang 评论 程序出现错误: ``` 2020/07/06 01:15:11 http: panic serving [::1]:51961: runtime error: invalid memory address or nil pointer dereference ``` 代码片段: ``` package service import ( "errors" "log" "fmt" "math/rand" "time" "../model" "../util" "github.com/go-xorm/xorm" ) type UserService struct { } var DbEngin *xorm.Engine // 注册功能, // mobile 手机号码 // plain_passwd :明文密码 // 昵称 // 头像 // 性别 func (s *UserService )Regisger(mobile,palin_passwd,nickname,avatar,sex string)( user model.User,err error){ //检测手机号码是否存在 test := new (model.User) // 同下面的&tmpUser fmt.Println("test===============") fmt.Println(test) tmpUser := model.User{} fmt.Println(tmpUser) fmt.Println(&tmpUser) fmt.Println(DbEngin) res,err := DbEngin.Where("mobile=? ",mobile).Get(&tmpUser) fmt.Println(res) if err != nil { log.Fatal(err.Error()) //return tmpUser,err } fmt.Println(tmpUser) if(tmpUser.Id>0){ //已经存在 return tmpUser,errors.New("该手机号码已经存在") } //写入到数据 tmpUser.Mobile = mobile tmpUser.Avatar = avatar tmpUser.Nickname = nickname tmpUser.Sex = sex tmpUser.Salt = fmt.Sprintf("%06d",rand.Int31n(10000)) tmpUser.Passwd = util.GenerPasswd(palin_passwd,tmpUser.Salt) tmpUser.Createat = time.Now() //插入数据库 _,err = DbEngin.InsertOne(&tmpUser) //恶意插入特殊字符串 if nil != err{ log.Fatal(err.Error()) } return tmpUser,nil } //登录service func (s *UserService)Login(mobile,plain_passwd string)(user model.User,err error){ //根据mobile,plain_paswd检测用户是否存在 tmpUser := model.User{} _,err = DbEngin.Where("mobile=?",mobile).Get(&tmpUser) if nil != err{ log.Fatal(err.Error()) } //验证正好和密码 passwd := util.GenerPasswd(plain_passwd,tmpUser.Salt) if(passwd == tmpUser.Passwd){ return tmpUser,nil } return model.User{},errors.New("账号或者密码错误") } ``` 经过排查,发现是这里 ``` _,err = DbEngin.Where("mobile=?",mobile).Get(&tmpUser) ``` 出现了问题,发现这里的DbEngin是为```nil```,所以出现非法的Point address 参考文档: 1. ```https://yourbasic.org/golang/gotcha-nil-pointer-dereference/```