Go函数知识

1.函数格式
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
//这里是处理逻辑代码
//返回多个值
return value1, value2
}
示例:
func max(a, b int) int {
if a > b {
return a
}
return b
}

2.多个返回值
func add(a, b int) (int,int) {
return a,a+b
}

3.参数个数不确定

func add(t ... int) (r int) {
for _, n := range t {
r+=n
fmt.Printf("And the number is: %d\n", n)
}
return
}

4.值传递和指针传递
值传递
func add(a int) int {
a=a+1
return a
}
func main() {
a:=1
b:=add(a)
fmt.Println(a)
fmt.Println(b)
}

指针传递
func add(a *int) int {
*a=*a+1
return *a
}
func main() {
a:=1
b:=add(&a)
fmt.Println(a)
fmt.Println(b)
}

5.defer
如果有很多调用defer,那么defer是采用后进先出模式可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回

6.函数作为类型
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])
备注:定义为typeName类型的函数当做值来传递

7.panic和recover

func badCall() {
panic("bad end")
}

func test() {
defer func() {
if e := recover(); e != nil {
fmt.Printf("Panicing %s\r\n", e)
}
}()
badCall()
fmt.Printf("After bad call\r\n") // <-- wordt niet bereikt
}

func main() {
fmt.Printf("Calling test\r\n")
test()
fmt.Printf("Test completed\r\n")
}

8.main和init
点操作:你可以省略前缀的包名,也就是前面你调用的fmt.Println("hello world")可以省略的写成Println("hello world")
别名操作:别名操作的话调用包函数时前缀变成了我们的前缀
_空操作:别名操作的话调用包函数时前缀变成了我们的前缀


Go的基础知识1

1.关键字
break    default      func    interface    select
case     defer        go      map          struct
chan     else         goto    package      switch
const    fallthrough  if      range        type
continue for          import  return       var

2.入口函数
每一个可独立运行的Go程序,必定包含一个package main,在这个main包中必定包含一个入口函数main,而这个函数既没有参数,也没有返回值。

3.定义变量
var name type //定义一个type类型的name变量
var name1,name2,name3 type //定义3个type类型的变量
var name type = value //定义type类型变量并初始化为value
var name1,name2,name3 type = v1,v2,v3 //定义三个type类型变量并分别初始化
var name1,name2,name3 = v1,v2,v3 //定义三个type类型变量并分别初始化
name1,name2,name3 := v1,v2,v3 //定义三个type类型变量并分别初始化,只能在函数内部用
_ 是特殊变量,任何值都会被舍弃

备注:变量如果声明未使用则会编译报错

4.常量
const name = value 定义一个常量,常量的值是数值、bool、
const name type = value 指定类型

5.数值类型
整数类型有无符号和带符号两种。Go同时支持int和uint,这两种类型的长度相同,但具体长度取决于不同编译器的实现。Go里面也有直接定义好位数的类型:rune, int8, int16, int32, int64和byte, uint8, uint16, uint32, uint64。其中rune是int32的别称,byte是uint8的别称。浮点数的类型有float32和float64两种(没有float类型),默认是float64。
Go还支持复数。它的默认类型是complex128(64位实数+64位虚数)。如果需要小一些的,也有complex64(32位实数+32位虚数)

6.字符串
字符串使用UTF-8字符集使用双引号或者反引号,类型是string
字符串可以使用+来连接
用反引号可以声明多行字符串

7.错误类型
内置一个error类型用来处理错误信息,还有一个errors的包可以处理错误

8.分组声明
import(
“fmt”
“os”
)
const(
i = 100
pi = 3.1415
prefix = “Go_”
)

9.iota枚举
const( 
x = iota
y = iota
z
)
那么y=1,z=2
备注:它默认开始值是0,const中每增加一行加1

const (
h, i, j = iota, iota, iota //h=0,i=0,j=0 iota在同一行值相同
)

10.设计原则
大写字母的变量是可以到处的
大写字母开头的函数等同public函数

11.数组array
var arr [n]type 声明一个type类型长度是n的arr数组
b := [10]int{1, 2, 3} //数组前三个元素用1 2 3初始化
c := […]int{4, 5, 6} //go自动计算数组长度
easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}} //声明二维数组

12.动态数组slice
var fslice []int  //声明数组,但不带长度
// 声明一个含有10个元素元素类型为byte的数组
var ar = [10]byte {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’}

// 声明两个含有byte的slice
var a, b []byte

// a指向数组的第3个元素开始,并到第五个元素结束,
a = ar[2:5]
//现在a含有的元素: ar[2]、ar[3]和ar[4]

// b是数组ar的另一个slice
b = ar[3:5]
// b的元素是:ar[3]和ar[4]

slice是引用类型,所以当引用改变其中元素的值时,其它的所有引用都会改变该值

13.map类型
map是无序的,每次打印出来的map都会不一样,它不能通过index获取,而必须通过key获取
map的长度是不固定的,也就是和slice一样,也是一种引用类型
内置的len函数同样适用于map,返回map拥有的key的数量
map的值可以很方便的修改,通过numbers[“one”]=11可以很容易的把key为one的字典值改为11
map和其他基本型别不同,它不是thread-safe,在多个go-routine存取时,必须使用mutex lock机制

composer开发的一些坑

1.问题描述:
 Your configuration does not allow connections to xxxxxx See https://getcomposer.org/doc/06-config.md#secure-http for details.
解决办法:
 "config":{
        "secure-http":false
    },
2.问题描述:
Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your min                                      imum-stability setting
   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more det                                      ails.
问题解决:
可能包不存在或者版本不存在
 

开发属于自己的composer

1.新建一个git仓库
备注:可以在github建立,如果要建立私有的composer,可以自己搭建git仓库

2.初始化composer文件
执行composer init
参考:https://getcomposer.org/doc/04-schema.md
{
    "name": "joyousphper/composer-demo",
    "description": "composer demo",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
          "name": "joyousphper",
          "email": "joyousphper@gmail.com"
        }
    ],
    "minimum-stability": "stable",
    "require": {
        "php": ">=5.4.0"
    },
    "autoload": {
        "psr-4": {
          "Tools\\": "src/Tools/"
        }
    }

}

3.编写代码并推送git仓库
新建src/Tools/Common.php
<?php
namespace Tools;

class Common
{
    public static function demo()
    {
        return 'hello world';
    }

}
添加标签
git tag -a v0.1.1 -m'第二个版本'
git push origin tag v0.1.1

4.提交composer
https://packagist.org/packages/submit

5.查看提交composer包
https://packagist.org/packages/joyousphper/composer-demo

6.设置composer自动更新
6.1打开https://github.com/JoyousPHPer/composer-demo/settings/installations添加一个Packagist服务
6.2https://github.com/JoyousPHPer/composer-demo/settings/hooks设置hook,这里的apitoken可以从https://packagist.org/profile/查看

7.项目引用
{
    "name": "joyousphper/demo1",
    "description": "composer demo",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
          "name": "joyousphper",
          "email": "joyousphper@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {
        "joyousphper/composer-demo": "v0.1.*"
    }
}

8.使用案例
<?php
require __DIR__ . '/../vendor/autoload.php';
use Tools\Common;

echo Common::demo();



phpspec入门

入门

  1. 执行bin/phpspec desc Markdown生成MarkdownSpec类
  2. 执行bin/phpspec run提示生成Markdown类
  3. 在MarkdownSpec类添加方法
    function it_converts_plain_text_to_html_paragraphs()
    {
        $this->toHtml("Hi, there")->shouldReturn("
<p>
    Hi, there
</p>
");
    }
  1. 执行bin/phpspec run提示生成Markdown类的toHtml方法
  2. 编写Markdown类的toHtml方法
    public function toHtml($argument1)
    {
        return "
<p>
    Hi, there11
</p>
";//这里故意写错
    }
  1. 执行bin/phpspec run
Markdown                                                                        
  11  - it converts plain text to html paragraphs
      expected "
<p>
    Hi, there
</p>
", but got "
<p>
    Hi, there11
</p>
".

                                      100%                                       1
1 specs
1 example (1 failed)
192ms

phpspec安装

安装

phpspec是一个php 5.6库,您将在项目开发环境中拥有它。在开始之前,请确保已经安装了PHP 5.6或7。

安装步骤

您可以通过Composer来安装phpspec。如果你还没有安装,请按照作Composer网站上的说明

安装方法1

执行命令composer require --dev phpspec/phpspec安装

安装方法2

1. 编辑composer.jsonrequire-dev节点添加”phpspec/phpspec”: “~3.0”
2. 执行composer update 或者composer install安装

composer内容
{
  “require-dev”: {
    “phpspec/phpspec”: “~3.0”
  },
  “config”: {
    “bin-dir”: “bin”
  },
  “autoload”: {
    “psr-0”: {
      “”: “src/”
    }
  }
}

Lumen5.X使用频率限制组件笔记

编写中间件,是根据vendor/illuminate/routing/Middleware/ThrottleRequests.php改写

备注:需要先配置cache

<?php

namespace App\Http\Middleware;

use Closure;
use Carbon\Carbon;
use Illuminate\Cache\RateLimiter;
use Symfony\Component\HttpFoundation\Response;

class ThrottleMiddleware
{
    /**
     * The rate limiter instance.
     *
     * @var \Illuminate\Cache\RateLimiter
     */
    protected $limiter;

    /**
     * Create a new request throttler.
     *
     * @param  \Illuminate\Cache\RateLimiter  $limiter
     * @return void
     */
    public function __construct(RateLimiter $limiter)
    {
        $this->limiter = $limiter;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  int  $maxAttempts
     * @param  float|int  $decayMinutes
     * @return mixed
     */
    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
    {
        $key = $this->resolveRequestSignature($request);

        if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
            return $this->buildResponse($key, $maxAttempts);
        }

        $this->limiter->hit($key, $decayMinutes);

        $response = $next($request);

        return $this->addHeaders(
            $response, $maxAttempts,
            $this->calculateRemainingAttempts($key, $maxAttempts)
        );
    }
    
    /**
     * Resolve request signature.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string
     */
    protected function resolveRequestSignature($request)
    {
        return sha1(
            $request->method() .
            '|' . $request->server('SERVER_NAME') .
            '|' . $request->path() .
            '|' . $request->ip()
        );
    }
//    protected function resolveRequestSignature($request)
//    {
//        return $request->fingerprint();
//    }

    /**
     * Create a 'too many attempts' response.
     *
     * @param  string  $key
     * @param  int  $maxAttempts
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function buildResponse($key, $maxAttempts)
    {
        $response = new Response('请求超出设定频率', 429);
        $retryAfter = $this->limiter->availableIn($key);

        return $this->addHeaders(
            $response, $maxAttempts,
            $this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
            $retryAfter
        );
    }

    /**
     * Add the limit header information to the given response.
     *
     * @param  \Symfony\Component\HttpFoundation\Response  $response
     * @param  int  $maxAttempts
     * @param  int  $remainingAttempts
     * @param  int|null  $retryAfter
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function addHeaders(Response $response, $maxAttempts, $remainingAttempts, $retryAfter = null)
    {
        $headers = [
            'X-RateLimit-Limit' => $maxAttempts,
            'X-RateLimit-Remaining' => $remainingAttempts,
        ];

        if (! is_null($retryAfter)) {
            $headers['Retry-After'] = $retryAfter;
            $headers['X-RateLimit-Reset'] = Carbon::now()->getTimestamp() + $retryAfter;
        }

        $response->headers->add($headers);

        return $response;
    }

    /**
     * Calculate the number of remaining attempts.
     *
     * @param  string  $key
     * @param  int  $maxAttempts
     * @param  int|null  $retryAfter
     * @return int
     */
    protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null)
    {
        if (is_null($retryAfter)) {
            return $this->limiter->retriesLeft($key, $maxAttempts);
        }

        return 0;
    }
}
//使用笔记
'middleware' => 'throttle:2,0.5'

php中的generator和yield

1.Generator
在编程这个领域,我们可以把它想象成一个可以生成一系列数据的工具,这个工具可以具体为一个类、一个函数或者是一个语句
定义:
http://de2.php.net/manual/en/class.generator.php
特点:
不能直接实例化使用new Generator()调用,必须使用yield

2.yield
在php中,yield关键字只能在函数中使用,代码执行到yield语句,函数的执行就会终止并返回yield表达式给Generator

当对Generator对象进行遍历迭代,那么带有yield语句的函数后的代码会执行
例子:
function a() {
    $b =23;
    yield $b;
    echo 1;
}
$c = a();
echo $c->current();//会输出23但是不会输出1
//遍历则会输出0=>23 1
foreach ($c as $k => $v) {
    echo $k . "=>". $v . PHP_EOL;
}

多条语句
function a() {
    yield 1;
    yield 2;
    yield 3;
}
$c = a();
//输出0=>1 1=>2 2=>3
foreach ($c as $k => $v) {
    echo $k . "=>". $v . PHP_EOL;
}
特性:每次迭代都只会执行前一次yield语句之后的代码,那Generator可以用于实现协程的原因。

3.用途
可以用来做协程
可以用来大量数据的集合(节约空间)

composer使用笔记

1.基本用法
require  monolog/monolog  1.0.*

2.包版本
确定版本	1.0.1
范围		>=1.0
范围AND		>=1.0,<2.0
范围OR		>2.0|<1.2
通配符		1.*
运算		~1.2等同于>=1.2,<2.0	大于1.2并且小于2.0版本

备注:~1.2.1是等同于>=1.2.1,<1.3

3.将composer.lock好composer.json提交到仓库当中方便协同工作

更多参考:https://getcomposer.org/doc/04-schema.md