置顶
【原创】 十六、价值投资基础知识
24 08 2025

价投基础知识与认知

        一、估值计算

        同比: 指当年的某个月与去年相同的月份进行对比  

        环比:指本次统计段与相连的上次统计段之间的比较   

        1、什么是PE ?

        PE:市盈率,股票估值指标,股价与每股收益的比率; PE=股价/每股收益。

        高PE:可能意味着市场对该公司未来的增长预期很高,也可能意味着股票当前被高估。

        低PE:可能意味着市场对该公司前景不看好,也可能意味着股票当前被低估,是买入的好机会。

        2、什么是静态市盈率?

        静态市盈率的本质是 “股价与过去一个完整会计年度净利润的比值”。

        计算公式:静态市盈率 = 当前股价 / 上一年度每股收益(EPS)      或者    静态市盈率 = 当前总市值 / 上一年度净利润

        TTM 是 “Trailing Twelve Months” 的缩写,意思是“过去十二个月”。所以,P/E TTM 就是用公司过去已经公布的、“最近12个月”的净利润来计算出的市盈率。

        3、什么是动态市盈率?

        动态市盈率(Dynamic P/E 或 Forward P/E,简称 PE(动))是股票估值中一个非常重要的指标。它和静态市盈率的主要区别在于所使用的“净利润”数据不同。

        计算公式:动态市盈率 = 当前总市值 / 未来预测的总净利润      或者     动态市盈率 = 当前股价 / 未来预测的每股收益(EPS)


        image.png

        4、预测和分析(新易盛案例)

        image.png


        image.png

        

        5、什么是PEG指标?

        一、核心定义

        PEG指标(市盈率相对盈利增长比率)是在市盈率(PE)的基础上发展而来的一个进阶估值指标。它的核心目的是解决一个关键问题:

        “一家公司的市盈率这么高,到底合不合理?它的高增长能 justify 它的高估值吗?”


        PEG的计算公式为:

        PEG = 市盈率(PE) / 净利润增长率(Growth Rate)

        市盈率(PE):通常使用动态市盈率(PE动),即基于未来12个月的预测盈利来计算。

        净利润增长率(Growth Rate):通常指公司未来几年预期的年均净利润增长率(以百分比表示,但计算时不带百分号)。


        二、为什么需要PEG?—— 从PE的缺陷说起

        单纯使用市盈率(PE)估值有一个巨大的缺陷:

        公司A:PE为30倍,但明年利润预计能增长50%。

        公司B:PE为15倍,但明年利润预计零增长。

        如果只看PE,公司B更“便宜”。但显然,公司A的高增长使其可能更具投资价值。PE指标无法将“增长”这个关键因素量化进估值里。

        PEG的诞生,正是为了将公司的市盈率与其盈利增长速度直接联系起来,从而更公允地评估不同成长性公司的估值水平。


        三、如何解读PEG值?

        PEG指标的理论由投资大师彼得·林奇(Peter Lynch) 发扬光大,他对其解读提供了一个经典的基准:

        PEG = 1:

        意味着公司的市盈率与其盈利增长率相匹配,估值处于“合理”或“公允”的水平。理论上,这是一家成长性与估值非常匹配的公司。

        PEG < 1:

        意味着公司的市盈率低于其盈利增长率。通常这表明公司可能被低估了(即股价“便宜”),因为投资者可以用较低的价格买到较高增长的公司。PEG越小,理论上低估的可能性越大。

        PEG > 1:

        意味着公司的市盈率高于其盈利增长率。通常这表明公司可能被高估了(即股价“偏贵”),市场为其增长支付了过高的溢价。PEG越大,高估的可能性越大。

        简单来说,PEG的核心思想是:追求用尽可能低的市盈率,购买尽可能高的盈利增长。


        四、如何计算PEG?—— 一个详细的例子

        假设我们分析一家公司:

        当前股价:100元

        今年预测每股收益(EPS):5元(因此其动态PE = 100 / 5 = 20倍)

        未来三年预测的年均净利润增长率:25%(分析师综合预测)

        那么,它的PEG计算如下:

        PEG = 动态PE (20) / 增长率 (25) = 0.8

        由于PEG=0.8 < 1,根据理论,这家公司可能处于被低估的状态,考虑其较高的增长率,20倍的PE显得并不贵。


        五、使用PEG指标的注意事项(非常重要!)

        PEG是一个非常强大的工具,但它严重依赖于输入数据的质量,使用时必须谨慎:

        增长率预测的准确性是关键:

        PEG中的“G”是对未来的预测,而不是历史数据。这个预测来自券商分析师、公司指引或投资者自己的判断。预测永远是错的,只能尽可能接近现实。对于周期性行业或业务不稳定的公司,预测误差会很大,PEG的参考价值会降低。

        选择正确的PE:

        一定要使用动态市盈率(Forward PE),即基于未来盈利的PE。使用静态市盈率(Past PE)计算PEG会得出非常误导性的结论。

        统一计算口径:

        确保PE和G的时间周期匹配。如果PE是基于未来一年的盈利(2025年),那么G就应该是未来一年的增长率(2025年 vs 2024年)。更常见的做法是,PE用未来一年的,G用未来3-5年的年均复合增长率。

        PEG更适用于成长股:

        该指标对于盈利稳定增长的公司最有效。对于周期性公司、陷入困境的反转型公司或利润波动极大的初创公司,PEG可能不太适用。

        不能孤立使用:

        PEG只是一个估值工具,不能作为投资的唯一依据。必须结合公司的基本面分析、行业前景、竞争优势、管理层质量等因素综合判断。


        总结

        PEG指标是市盈率(PE)的优化版本,它通过引入盈利增长率(G),将估值与成长性捆绑评估,解决了“高PE是否合理”的问题。

        PEG ≈ 1:估值合理

        PEG < 1:可能低估(值得关注)

        PEG > 1:可能高估(需要警惕)



        二、段永平对企业未来现金流折现和估值具体思路

        核心观点:  段永平并不是在真正地、精确地积算仪各公司的DCF(现金流折现),他多次强调,DCF不是一个计算公式而是一种思维方式!!!

        核心思路:

        1. 定性分析优先: 在思考任何数字之前,首先要判断这家公司是不是一家“好公司”。好公司的标准是:

           · 强大的护城河: 拥有强大的品牌(如茅台)、技术领先(如苹果),使得竞争对手难以超越。

           · 优秀的商业模式: 能持续产生充沛的自由现金流,并且不需要持续的大额资本支出来维持竞争力。

           · 可信赖的管理层: 管理层以股东利益为导向,诚实、能干。

        2. 思考未来现金流的确定性: 对于筛选出的好公司,重点思考其未来(比如5年、10年甚至更久)赚取自由现金流的能力是否足够稳定和可预测。如果一家公司的未来现金流非常模糊、波动巨大,那么它就不适合用DCF(现金流折现)思维来估值。

        3. “毛估估”代替精确计算: 基于对公司的深刻理解,对一个“大概”的未来现金流和其增长率进行估算。关键在于 “宁要模糊的正确,不要精确的错误” 。他追求的是一个价值区间,而不是一个精确的数字。


        具体步骤(“毛估估”版DCF)


        虽然不进行精确计算,但其思考过程暗含了DCF的逻辑。我们可以将其分解为以下步骤:


        步骤一:找到“正确的石头”——选择标的


        这是所有步骤的前提。只选择那些你真正理解、商业模式简单、现金流稳定的好公司。段永平的投资组合(苹果、茅台、腾讯等)都符合这个特征。


        步骤二:估算未来一段时间的自由现金流


        1. 确定当前的自由现金流: 找到公司目前能产生的“所有者盈余”(经营活动产生的现金流量净额)。一个简化的算法是:自由现金流(更纯的所有者盈余) = 经营活动现金流净额 - 资本性支出。

        因为企业为了维持现有的生产经营能力,必须进行必要的资本再投资(如更换老旧设备、升级厂房)。扣除这部分维持性支出后剩余的现金流,才是企业可以自由支配且不会损害其未来竞争力的“盈余”,这部分才能真正安全地分配给所有者或用于新的发展机会。

        资本性支出:

        ① 购置新的固定资产:如土地、厂房、机器、设备、车辆。

        ② 购置新的无形资产:如软件、专利、许可证。

        ③ 对现有资产进行重大升级、改造和扩建。

        ④ 为战略性扩张而进行长期的资产投资。

        注意:财报中的“投资活动产生的现金流量”部分,一个关键的行项目:“购建固定资产、无形资产和其他长期资产支付的现金”,这是一个非常直接地反映企业当期资本性支出现金总额的指标。


        2. 估算一个保守的增长率: 根据对行业前景、公司竞争力的理解,给未来5-10年一个保守的、可持续的增长率。例如,对于茅台,他可能会认为其销量和价格在未来10年有一个稳定的低速增长。

        3. 估算第一阶段的价值: 将未来几年(比如10年)的现金流,以一个保守的增长率进行估算,并加总。这是一个简化的“高速增长期”模型。


        步骤三:确定折现率


        段永平对折现率的看法非常经典。他认为折现率就是无风险收益率,通常用长期国债的利率(2.3% -- 2.5%)作为参考。


        · 逻辑是: 投资一家公司的最低要求回报,至少要高于无风险收益。如果一家公司的预期回报率还比不上国债,那为什么不直接买国债呢?

        · 实际操作: 他会用一个相对固定的比率,比如5%或10%,来简化思考。这个比率反映了他的机会成本和对风险的最低要求回报。


        步骤四:估算永续价值


        这是DCF模型中最关键也是最难的部分。段永平的简化方法是:


        1. 假设永续增长率为0: 为了保守起见,他通常假设公司在高速增长期结束后,进入零增长阶段,其价值就等于一个永续年金。

        2. 计算公式(简化版):

           · 永续价值 = 第N年的自由现金流 / 折现率

           · 例如,如果估算10年后公司的年自由现金流是200亿,折现率是5%,那么永续价值 = 200 / 5% = 4000亿。

        3. 将这个永续价值折现到现在,加上第一阶段现金流的现值(将未来几年的现金流,以一个保守的增长率进行估算,并加总),就得到了企业的大概内在价值。

        总内在价值 = 永续价值折现 + 第一阶段现金流的现值


        一个简化的实例(以茅台为例)


        假设我们正在“毛估估”茅台的价值:


        1. 定性判断: 茅台品牌无敌,护城河极深,商业模式好(先款后货,现金流极好)。这是一块“正确的石头”。

        2. 估算当前现金流: 假设茅台目前年自由现金流约为800亿元。

        3. 估算未来增长: 保守估计,未来10年其自由现金流能以每年6%的速度增长。

           · 第1年后的现金流 ≈ 800 * (1.06)^1 ≈ 848亿元。

            ......

            ......

           · 10年后的现金流 ≈ 800 * (1.06)^10 ≈ 1432亿元。

        4. 确定折现率: 采用5%作为折现率(高于长期国债利率,考虑了机会成本)。

        5. 计算永续价值:

           · 10年后的永续价值(假设零增长)= 1432 / 5% = 28,640亿元。

           · 将永续价值折现到今天 = 28,640 / (1.05)^10 ≈ 17,582亿元。

           总内在价值 = 17582+第一年 + 第二年 +...... + 1432 = 大约30000亿(未详细计算)

        6. 得出结论: 茅台的内在价值大概在3万亿左右。然后与当前市值比较,如果当前市值远低于这个“毛估估”的价值,就可能是一个好的投资机会。


        总结与精髓


        段永平的DCF方法,精髓在于:


        1. 思维模型而非计算工具: 它强迫你从企业所有者的角度去思考生意本身,关注其长期现金创造能力。

        2. 追求模糊的正确: 承认未来的不可预测性,通过保守的假设(低增长率、高折现率/零永续增长)来寻求安全边际。

        3. 能力圈原则: 只对少数你能理解的、商业模式简单的公司使用这种方法。

        4. 简单化: 避开了复杂的财务模型和变量预测,直指核心——这家公司在它的生命周期里,能为股东带回的现金,比我现在付出的价格多吗?


        最终,段永平通过这种思维方式,将投资的复杂问题简化为一个本质问题:用4毛钱的价格,去购买价值1块钱的资产。 DCF思维就是帮助他判断那个资产“到底值1块钱还是8毛钱”的思考框架。


        三、市场中轻资产行业分类

        “轻资产行业”通常指那些资本投入较少、固定资产占比较低、更多依赖无形资产(如智力资本、品牌、技术、网络和人力资本)来运营和创造价值的行业。其核心特点是:固定成本低,可变成本高,扩张的边际成本低,因此通常具有较高的毛利率和较强的 scalability(可扩展性)。


        1. 互联网

        ① 软件开发 

            例子:微软(Office 365)、Adobe(Creative Cloud)、Salesforce、用友网络、金山办公。它们主要投入在研发上,产品通过云端交付,几乎没有实物库存。

        ② 互联网与社交平台

            例子:腾讯(微信、QQ)、字节跳动(抖音、TikTok)、微博、Meta(Facebook, Instagram)。它们构建平台,连接用户和内容创作者/商家,通过广告、增值服务等盈利。

        ③ 电子商务平台

            例子:阿里巴巴(淘宝、天猫)、京东(平台业务)、拼多多、亚马逊(第三方 marketplace 业务)。它们自身不持有大量库存,而是为买家和卖家提供交易场所,赚取佣金和广告费。

        ④ 云计算与IT服务

            一、一梯队

            这些公司提供基础的计算、存储、网络资源,并在此基础上构建了庞大的云生态。

            阿里巴巴-阿里云     腾讯-腾讯云    百度-百度云

            二、二梯队,传统IT服务商转型

            这些公司由传统的系统集成、软件服务商转型而来,在特定行业有深厚的客户积累。

            金山软件、用友网络、东软集团、中国电信-天翼云 、中国移动-移动云

            三、三梯队,垂直领域/专业云服务商

            广联达:建筑信息化领域的龙头,其核心产品“数字造价”业务已全面转型为SaaS模式,是垂直SaaS云服务的典范。

            恒生电子:金融科技领域的绝对龙头,为证券、基金、银行、期货等金融机构提供软件和云服务,其“云赢”、“云毅”等产品是金融云的代表。

            深信服:最初以网络安全闻名,现在其云计算业务(超融合、桌面云)增长迅速,为企业提供“软件定义”的IT基础设施。

            四、四梯队, IDC(互联网数据中心)服务商

            万国数据:中国领先的高性能数据中心开发商和运营商,主要服务大型云厂商和互联网公司。

            数据港:国内领先的数据中心服务提供商,与阿里云等有深度合作。

            宝信软件:背靠宝钢集团,依托资源优势发展IDC业务,同时自身也是工业软件和IT服务解决方案提供商。



        2. 科技研发类

        ① 人工智能行业

            核心资产是算法团队和数据资产,依赖云算力开展业务,无需大量固定资产。比如智齿科技的 AI 客服、推想科技的智能医疗诊断系统,通过 API 调用、定制化模型开发盈利,毛利率常达 70%-90%。

        ② 半导体设计行业

            采用 Fabless 模式,仅专注芯片设计,制造环节外包给台积电等代工厂,无需自建百亿级晶圆厂。像芯动联科的 MEMS 陀螺仪芯片、汇川技术的工业控制芯片,靠电路架构设计和 IP 授权实现 50%-70% 的高毛利。

        ② 精准医疗与生物技术行业

            核心资产为研发团队和生物数据,实验室设备可租赁或外包。例如燃石医学的肿瘤 NGS 检测服务、英矽智能的 AI 药物研发平台,诊断服务和创新药相关业务毛利率普遍超 80%。



        3. 专业服务类

        ① 咨询行业

            管理咨询(麦肯锡、波士顿)、战略咨询、人力资源咨询、财务咨询。

        ② 法律服务

            律师事务所、知识产权代理。

        ③ 会计与审计服务

            会计师事务所、税务筹划公司。

        ④ 广告与营销策划

            广告创意公司、数字营销机构、品牌策划公司。

        ⑤ 设计服务

            UI/UX设计、平面设计、工业设计、建筑设计(部分为轻资产模式)。


        4. 文化创意类

        ① 影视与娱乐制作

            独立制片公司、短视频工作室、MCN机构。

        ② 游戏开发

            尤其是独立游戏团队、手游开发商(依赖代码和创意而非硬件)。

        ③ 出版与内容发行

            数字出版、电子书平台、自媒体出书。

        ④ 艺术与版权运营

            IP授权、动漫形象运营、文创产品设计(外包生产)。


        5. 金融与投资类

        ① 投资银行与券商

            例子: 高盛、摩根士丹利、中信证券。主要业务如承销、并购顾问等,依赖人力资本和金融牌照。

        ② 资产管理

            例子: 贝莱德、富达基金、华夏基金。通过管理客户的资产收取管理费,核心是投资研究能力。

        ③ 支付与金融科技

            例子: 支付宝、PayPal、Visa、Mastercard。构建支付网络,处理交易流,赚取手续费。


        6. 共享经济与平台型服务类

        ① 共享出行平台

            如:滴滴、Uber(不拥有车辆,只提供平台)。

        ② 共享住宿平台

            如:Airbnb、途家(不持有房产)。

        ③ 众包服务平台

            如:猪八戒网(连接服务提供者与客户)。


        7. 电商与新零售类

        ① 品牌电商运营(无自有工厂)

            如:许多DTC品牌(Direct-to-Consumer),通过代工生产+线上销售。

        ② 跨境电商(轻模式)

            如:Shopify独立站卖家、亚马逊FBA卖家(仓储由平台负责)。

        ③ 社区团购平台

            仅做信息撮合与供应链管理,不自建物流。


        8. 健康与个人服务类

        ① 在线医疗咨询

            医生在线咨询平台,不设实体医院。

        ② 健康管理与健身指导

            如:线上私教、健康APP、营养咨询服务。

        ③ 心理咨询与辅导

            在线心理咨询服务,依赖专业人才而非场地。

        例子: 专科诊所(如牙科、眼科连锁)、互联网医疗平台(如平安好医生)。更依赖医生技术和品牌,而非大型医疗设备。


        总结:轻资产行业的共同特点!!!

        核心价值在于无形资产:品牌、专利、版权、技术、数据、人力资本、商业模式。

        固定资产占比低:不需要大量投资在厂房、机器设备上。

        运营杠杆高:一旦核心系统/平台建成,服务额外客户的边际成本很低。

        现金流通常较好:由于前期资本开支小,现金回收快。

        易于快速扩张和复制:例如,一个成功的软件或商业模式可以迅速推广到全球。


        四、商业模式优秀、盈利能力强、负债率低的行业

            在国内,能够被称为商业模式顶尖、利润丰厚、负债率低的行业,通常具备以下几个核心特征:

          高毛利率 & 高净利率

          轻资产运营(低资本开支)

          强定价权或垄断/寡头格局

          现金流充沛、分红稳定

          护城河深(品牌、牌照、网络效应等)


        1、白酒(高端白酒)

        特点:

        毛利率 >80%,净利率 >40%(如茅台净利率超50%)

        几乎零应收款、预收款模式(先款后货)

        库存不贬值反而升值(老酒越存越值钱)

        品牌护城河极深,难以被替代

        资产负债率普遍低于30%


        2、互联网平台/数字经济(头部企业)

        特点:

        轻资产、高毛利(软件/服务为主)

        用户规模带来数据和流量壁垒

        现金流好,资本开支相对可控

        头部企业净利率可达20%-40%+

        image.png


        3、免税零售(政策垄断)

        国家特许经营、牌照稀缺、利润率惊人

        特点:

        image.png


        4、医疗服务/创新药(细分龙头)

        image.png


        5、软件与信息技术服务(Saas、金融科技)

        image.png


        6、公用事业中的优质行业(水电、核电)

        image.png


        7、消费类垄断品牌

        image.png





        

        







置顶
【原创】 七、有关经济的一些基础知识
11 08 2022

基础知识与认知

        一、CPI指标

        同比: 指当年的某个月与去年相同的月份进行对比  

        环比:指本次统计段与相连的上次统计段之间的比较   

        1、什么是CPI ?

        消费者物价指数,又称居民消费价格指数

        2、CPI上涨与下跌的影响?

        image.png

        image.png


        二、PPI指标

        1、什么是PPI ?

        PPI指的是生产价格指数,反应的是工业品出厂价格的变化,PPI下降表名原材料价格跌幅比较大,PPI下降是不好的,但也不是越高越好,它的波动反应了实体经济的景气程度。

        2、PPI指标调查的商品?

        燃料、化工原料、钢材、木材、水泥、农副产品、工控产品等,主要用来预测未来物价变化的宏观经济数据指标。


        三、经济放水

        1、经济放水的代表“安bei经济学”

        大概意思理解为,经济不好的时候ZF把钱花出去,带动经济发展。

        弊端:往一个池子注水注多了以后,水会涨起来。同样的道理,经济放水以后股市会涨、债券会涨、商品价格会涨,物价会上升。

        加息:最近几年疫情影响,包括美国在内的一些国家为了保住经济,进行大放水,放水以后物价上涨,石油、粮食、猪肉、能源等等都在涨,物价上涨,钱就不值钱了。 为了控制气球吹大以后不会自己爆,就要放点气,怎么放呢,通过加息。因为钱是临时应对不景气的经济,从ZF那里印出去的,当然要收回来。当美国进行加息以后,那些在美国贷款的人就要回去还本金+高额利息,在世界范围内的投资者自然要抛掉手中股票、房产、债券等回去还钱。

        CPI:2022/8/10 美国公布CPI比上一期降低,比预期还低0.2个点,这样美国ZF就会放缓加息的预期,美股大涨,A50也大涨,2022/8/11世界范围内的资金也放心的开始流动,内资外资都在爆买。美国ZF放缓加息的预期,同时美元指数在下跌,人民币以及非美货币就会有一定的升值, 如果人民币下跌,就会导致一些外资的出逃(美元必须兑换成人民币才能买进A股,如果人民币下跌,兑换成人民币以后哪怕不买股票只是逛一圈,资产就缩水了),2022/8/11美元指数下跌,人民币汇率反弹,外资回流,几十亿上百亿的外资回流,肯定是不会去小盘子股的,要去也是去蓝筹股、金融股等,所以2022/8/11当天动的是券商(金融)、茅台、五粮液、歌尔股份、中国船舶、比亚迪等蓝筹股


        四、世界经济与美国经济

        1、美元成为国际货币的历史因素

        在二战以后,美国逐渐确立了其在世界经济和军事领域的领先地位,欧洲大陆国家与美国达成协议同意使用美元进行国际支付,此后美元作为储备货币在美国以外的国家广泛使用并最终成为国际货币。

        要想成为国际货币,除了汇率稳定以外,还有其他系列因素,更多的政治因素。至于美元还能在世界上使用多少年,还取决于世界其他国家的发展和美国自身的发展。


        五、股市级别

        1、点

        买卖点、K线、MACD、等等xx指标

        2、线

        热点板块、市场人气/市场情绪、图形(头肩顶、M顶、W底、多头排列等等)

        3、面

        资金流向、经济指标、国家CPI数据、美国CPI数据、美国加息、世界经济形势、世界大宗商品价格、地缘政治等等


        六、解禁

        1、解禁

        股票解禁是指公司股票持有人在规定时间内可以自由出售其持有的股票。在企业股票上市时,可能会存在股票锁定期,期间股东不得出售其持有的股票。一旦锁定期结束,股票就会解禁,股东可以自由出售其持有的股票。

        通常情况下,当一个公司的股票解禁之后,其股票供应量会增加,这可能会影响股票价格。如果解禁的股票数量很大,市场供应将会更加充裕,可能导致股票价格下跌。


        七、一级市场和二级市场

        股市的一级市场和二级市场存在几个主要的区别:

        1、交易性质:

        一级市场:一级市场是公司通过发行股票或其他金融工具来筹集资金的场所。在这个市场中,投资者直接购买公司发行的新股,这些股票通常来自公司的首次公开募股(IPO)。一级市场的交易对公司来说是首次发行股票的过程。

        二级市场:二级市场是指公司股票在一级市场发行并上市后,投资者之间互相买卖股票的地方。在这个市场中,股票价格的变动不受公司股本变动的影响,而是取决于市场供需关系和其他多方面的因素。

        2、交易主体:

        一级市场:交易主体包括上市公司、投资者、股票承销商等。一级市场的参与者通常是直接与公司接触的个人或机构投资者,他们可能会参与公开发行或定向发行过程。

        二级市场:二级市场的交易主体主要是个人投资者和机构投资者。他们在二级市场上进行的交易是不受公司股本变动影响的,因此不需要考虑公司内部的变化,更多的是关注市场行情和技术分析等因素。

        3、交易方式和规则:

        一级市场:一级市场的交易方式包括公开发行和定向发行两种。公开发行的股票会在证券监管部门注册登记,而定向发行则是向特定对象发行股票。

        二级市场:二级市场的交易方式包括集中竞价和协议转让两种。集中竞价是通过证券交易所的电子系统进行撮合的交易方式,而协议转让则是在证券交易所之外通过双方协商确定的交易方式。

        4、流动性:

        一级市场:一级市场上的股票可能存在限售期,在这段时间内股票不能上市交易流通。因此,一级市场的流动性相对较低。

        二级市场:二级市场的股票没有限售期,交易比较自由,流动性相对较高,通常在交易时间内可以随时交易。

        5、信息透明度

        一级市场:一级市场是非公开的,信息的透明度相对较低,投资者在投资时需要更多的信息和判断力。

        二级市场:二级市场是公开的,投资者可以通过各种渠道获取相关信息,这使得市场情绪可以被利用。


        八、什么是重资产企业

        1、释义

        高额固定资产投入:公司的资产负债表上,“固定资产”科目金额非常庞大,占总资产的比重很高。启动和运营需要巨大的前期投资。

        高折旧成本:厂房、机器设备等会随着时间推移而损耗贬值,这部分价值会以“折旧”的形式计入当期成本,侵蚀企业利润。

        高财务杠杆:由于初始投资巨大,企业往往需要通过银行借款或发行债券来融资,导致资产负债率较高,财务风险也随之增加。

        规模经济效应明显:一旦固定资产投入完成,产量越大,单位产品所分摊的固定成本(如折旧)就越低,企业就越能盈利。因此,它们非常追求产能利用率和市场规模。

        进入和退出壁垒高:

        进入难:新竞争者很难筹集到足够的资金来复制同样的生产设施。

        退出难:那些昂贵的专用设备很难转卖或转作他用,沉没成本极高。

        2、行业举例

        汽车制造、钢铁厂、半导体芯片制造(台积电)、能源资源行业、交通运输(航空公司购买飞机、铁路公司铺设铁轨)、大型连锁超市(购买租赁土地房产) 、顺丰(自购飞机、建设机场、中转中心)


        九、什么是轻资产企业

        1、释义

        与重资产企业相对的是轻资产企业。这类企业主要依靠自身的知识产权、品牌、人力资本、管理流程、客户关系等无形资产来创造价值,而不依赖于拥有大量的有形固定资产。

        2、行业举例

        互联网公司:阿里巴巴、腾讯、

        软件公司:微软、Adobe

        品牌管理公司:如耐克(主要专注于设计和营销,生产大多外包)。

        咨询公司:如麦肯锡(核心资产是人才和知识)。


        十、资产负债率

        1、释义

        资产负债率是衡量企业财务结构和风险水平的核心指标,计算公式为:

        资产负债率 = 总负债 ÷ 总资产 × 100%。该指标越高,通常代表企业的 “负债依赖度” 越强,但具体含义需结合行业特性、企业阶段和财务策略综合判断,不能简单等同于 “风险高” 或 “经营差”。

        资产负债率的本质是 “企业资产中有多少是靠借钱形成的”。例如,资产负债率 60% 意味着:企业每 100 元资产中,有 60 元来自负债(如银行贷款、应付账款),仅 40 元来自股东投入(净资产)。

        指标越高,说明企业对外部资金(负债)的依赖程度越高,自身权益资金的 “撬动作用” 越强 —— 这种 “以债扩资” 的模式,既是一把 “双刃剑”,也反映了企业不同的经营逻辑。


        十一、同比环比

        1、同比

        定义:同比是指与上年度的同一时期进行比较。

        计算公式:同比增长率 = (本期数值 - 上年同期数值) / 上年同期数值 × 100%

        2、环比

        定义:环比是指与紧相邻的上一个统计周期进行比较。

        计算公式:环比增长率 = (本期数值 - 上期数值) / 上期数值 × 100%


        十二、定增

        1、定义:“企业搞定增” 指的是上市公司通过定向增发(简称“定增”)的方式再融资。

        定向:意思是“面向特定对象”,不是所有股民都能买。

        增发:意思是“增发新股”,公司新发行一部分股票。

        合起来就是:上市公司选择一些特定的、符合条件的投资者(通常数量不多),以一定的价格向他们新发行一批股票,从而从这些投资者手里融到一笔资金。

        2、定增的关键特点

        ① 打折买股票:为了吸引这些大佬来投资,定增的价格通常会有折扣,比市价要低一些(一般是不低于市价的80%)。这是定增对投资者最大的吸引力之一。

        ② 锁定期:这些“大佬”买了定增股票后,不能马上卖掉套现。按照规定,他们有至少6个月的锁定期(如果认购后成为公司控股股东或实际控制人,则锁定期为18个月)。这保证了公司资金的稳定,也防止他们短期套利走人。

        ③ 特定投资者:这些“大佬”不是普通人,通常是:

        实力雄厚的机构投资者(如公募基金、私募基金、证券公司、信托公司等)

        有资源的战略投资者(比如公司的上下游合作伙伴,能带来业务协同效应)

        少量的超级富豪(个人资产门槛很高)


        十三、投资的本质

        1、定义:忘掉是在买股票,想象自己是在做一门生意。

        2、生意的本质

        ① 它如何赚钱?(盈利模式)

        靠卖产品?(茅台卖酒)、提供服务?(腾讯云提供云服务)、收取佣金?(券商)

        ② 它赚钱容易吗?

        品牌护城河:(如茅台) 用户愿意为品牌支付溢价。

        网络效应护城河:(如微信、抖音) 用户越多、价值越大,新来者难以超越。

        技术护城河:(如台积电、苹果)  拥有别人难以轻易复制的专利或者技术。

        特许经营护城河:需要政府拍照,准入门槛极高。

        ......    

        3、现金流本质

        投资的回报,最终必须真实的体现为现金流的回报。

        ① 未来自由现金流折现 (公司可以自由支配,不影响经营的钱)

        

        4、市场预期的本质

        市场价格(股价)并不总是等于内在价值,价格围绕价值波动,而驱动波动的,是市场预期。

        价格 VS 价值

        ① 价格是你付出的,价值是你得到的。

        ② 投资的奥秘在于:在市场预期低迷,价格远低于内在价值时买入;在市场预期狂热,价格远高于内在价值时卖出。

        5、人性的本质

        这是最难的一关,因为你要对抗的是自己的“人性”。

        ① 贪婪与恐惧 

        ② 从众,没有自我主见,别人说什么就跟随什么,而自我主见需要具有深刻的了解与认知。

        ③ 过度自信与厌恶损失  赚钱了,自己能力,亏损了,归咎于市场


        总的来说,投资的本质就像“剥洋葱”

        ① 最外层(现象):价格波动、新闻消息、K线图。

        ② 中间层(分析):市场预期、情绪博弈。

        ③ 最内层(核心):生意的本质+现金流价值+对人性的克服。

        真正的投资,永远穿透表层的喧嚣,直达最内层的核心,用合理的价格,买入一门能持续产生丰厚现金流的好生意,并有足够的耐心与定力陪伴其成长。






        

        




        





















置顶
【原创】 Linux 用户管理和服务管理
11 03 2021

五、Linux用户管理和服务管理

一、用户管理命令

        摘要:

                用户信息文件: /etc/passwd

                        user1:x:500:500::/home/user1:/bin/bash

                        图片.png

                        第一列:用户名

                        第二例:密码位(x代表设置了密码)

                        第三列:UID                用户ID

                                0:                       超级用户

                                1-499:                系统用户(伪用户,不允许登录linux,绝对不允许删除,是用来启动linux服务或者命令或者程序的)

                                >500:                 普通用户        (默认500-60000)

                        第四列:GID                 初始组ID

                        第五列:用户说明

                        第六列:家目录

                        第七列:用户登录之后的权限

                                    /bin/bash

                        

                        影子文件:        /etc/shadow        (用户密码保存文件,权限000,root也要wq!才能保存)

                        组信息文件:    /etc/group

                            sc : x : 500 :

                            组名:组密码位:组ID:组中附加用户

                        图片.png

                        windows创建的用户都在user组

                        图片.png

                    

                    图片.png

                       


        1、添加用户

            useradd    用户名    添加用户

            useradd    选项    用户名

            选项:

                    -g    组名    指定初始组                不要手工指定

                    -G    组名    指定附加组,把用户加入组,使用附加组

                    -c     说明     添加说明

                    -d     目录    手工指定家目录,目录不需要事先建立

                    -s     /bin/bash    手工指定用户登录之后的权限

                    -u    uid:        指定UID

                    

                    图片.png

                

                    useradd    -g    aa    bb        添加bb用户,同时指定初始组为aa

                    useradd     -G    user1    aa         添加用户aa,指定附加组为user1

                   

                    gpasswd    -a    用户名    组名    

                    useradd     -g    组名    用户名

                    

                    user1:

                    初始组:每个用户初始组只能有一个,一般都是和用户名相同的组作为初始组

                    附加组:每个用户可以属于多个附加组,要把用户加入组都是加入附加组

        2、设定密码

                    passwd    用户名

                    passwd                    改变当前用户密码

                    passwd    user1        改变user1用户密码

        3、删除用户

                    userdel    -r    用户名            -r连带家目录一起删除

        4、添加组

                    groupadd    组名

        5、删除组

                    groupdel    组名        注意:组中没有初始用户

        6、把已经存在的用户加入组

                     gpasswd    -a    用户名    组名            把用户加入组

                     图片.png

                     gpasswd    -d    用户名    组名            把用户从组中删除 

二、用户相关命令

        1、id    用户名            显示用户的UID,初始组合附加组

                     图片.png                                              

        2、su    -    用户名        切换用户身份            - 连带环境变量一起切换  

             env    查看Linux操作环境        

三、ACL权限    用来解决用户对文件身份不足的问题       

        举例:/work          项目提交目录

                所有者、所属组有提交更改创建权限,其他人无任何权限

                leigong --> 所有者

                lggroup --> 所属组

                /work/      权限 770

        操作:

                mkdir    /work

                chmod    770    /work/

                useradd     leigong

                groupadd    lggroup

                gpasswd    -a     leigong    lggroup   (所有者加入组)

                将所有者leigong加入到lggroup组中

                gpasswd    -a    user1    lggroup      (用户user1加入组)

                将用户user1加入到lggroup组中

                chown    leigong:lggroup    /work

                ll    -d    /work/

                图片.png  

        1、getfacl    文件名    查询文件的acl权限

        2、setfacl    选项    文件名    设定acl权限

                            -m                   设定权限

                            -b                    删除权限

               图片.png   

              班主任以5权限进到了work目录

               图片.png

             删除facl权限

             图片.png  

             

               setfacl    -m    u:用户名:权限    文件名

               setfacl    -m    g:组名:权限        文件名

                

                setfacl    -m    u:aa:rwx    /test            给test目录赋予aa是读写执行的facl权限

                setfacl    -m    u:cc:rx    -R    soft/        递归赋予acl权限,只能赋予目录

                -R    递归

                setfacl    -b    /test                                删除acl权限

                setfacl    -x    u:用户名    文件名             删除指定用户的ACL权限      

        3、setfacl    -m d:u:bzr:5    -R    /work/        acl设置默认权限   d(default) 

                图片.png          

                

                图片.png

                注意:默认权限只能设置目录

                注意:如果给目录赋予acl权限,两条命令都要输入

                setfacl    -m    u:用户名:rx    -R  文件名            只对已经存在的文件生效       

                setfacl    -m    d:u:bzr:rx    -R    文件名            只对未来要新建的文件有效 

四、输出重定向和多命令顺序执行

        1、输出重定向        (把应该输出到屏幕的输出,重定向到文件)

                >    覆盖的方式写进文件

                >>    追加的方式写进文件

                ls    >    aa    覆盖到aa

                ls    >>    aa    追加到aa

                ls    fdhfjsolk    2>>aa    错误信息记录到aa文件        2    错误信息        注意:错误输出,不能有空格

                图片.png    

               掌握:

                       ls    >>    aa    2>&1                        错误和正确都可以输入到aa,可以追加,  2&1把标准错误重定向到标准正确输出

                       ls    >>    aa    2>>/tmp/bb          正确信息输入aa,错误信息输入bb

五、服务和进程管理

        进程管理三个主要任务:

                判断服务器健康状态        正常、非法            top

                查看所有正在运行的进程            ps    pstree

                强制终止进程            kill    pkill

                服务器合理资源范围            70/90:内存占用不超过70%,CPU占用不超过90% 

                      

        一、进程查看      

            1、ps    aux        查看当前系统所有运行的进程     

                    -a    显示前台所有进程

                    -u    显示用户名

                    -x    显示后台进程

            服务器遵循70/90原则,即内存占用率不超过70%,CPU占有率不超过90% !!!


图片.png

                    user:        用户名

                    PID:         进程ID                PID=1的进程永远是/sbin/init    系统启动的第一个进程

                    %CPU:        CPU占用百分比

                    %MEM:       内存占用百分比  

                    VSZ:            虚拟内存占用量        KB

                    RSS:          固定内存占用量

                    TTY:           登录终端     tty1-7本地终端        1-6字符,7图形;pts/0 - 255    远程终端

                    STAT:        进程状态    S:睡眠    D:不可唤醒    R:运行    T:停止    Z:僵死    W:进入内存交换    X:死掉的进程    <:高优先级    N:低优先级    L:被锁进内存    s:含子进程    +:位于后台    l:多线程      

                    START:       进程触发时间

                    TIME:         占用CPU时间

                    COMMAND:    进程本身

         2、pstree    查看进程树

                pstree    -p    查看进程树(包括inode号)

                图片.png

         3、top

                图片.png

            

             第一行:系统当前时间    系统持续时间    登录用户数量    1,5,15分钟之前的平均负载

             第二行:进程总数         进程总数125个,1个运行,124个休眠

             第三行:CPU占用率            %id空闲辈分比

             第四行:内存使用    总共        使用        空闲        缓存

             第五行:swap使用 

             可通过1,5,15分钟之前的平均负载、CPU空闲率、内存空闲率判断服务器的基本压力

             操作命令:

                    M:内存排序

                    P: CPU排序

                    q: 退出

        4、进程管理    终止进程     (没事别老杀进程,apache、mysql等进程都有启动终止命令)

                kill    信号    PID        结束单个进程

                        -9    强制

                killall    -9    进程名        结束一类进程

                pkill     -9    进程名         结束一类进程   


                w     判断登录用户            

                图片.png

                pkill    -9    -t    终端号        把某个终端登录的用户踢出去(只有超级用户才能提其他用户)

                pkill    -9    -t    pts/0            把user1用户踢下去,踢完之后user1用户连接状态变成了红色

                图片.png     

六、Linux服务管理

        默认情况下,所有的服务管理命令(如:service、ntsysv、chkconfig)都不能识别源码包安装的服务        

        一、分类

            RPM包安装的服务

            1、独立的服务  (独立服务放在内存,直接响应速度快;缺点占内存)

                    启动:

                        A:service    服务名    start|stop|restart

                        B:/etc/rc.d/init.d/服务名    start      标准启动

                    自启动:

                        A:chkconfig    --level    2345(开机级别)    httpd    on|off

                        B:vi    /etc/rc.local  

                                    /etc/rc.d/init.d/httpd start   (建议用第二个)

            2、基于xinnetd的服务   (xinetd服务自己占内存,它管理的服务部占内存,缺点慢;;用得越来越少)

                图片.png

              

                ntsysv

                源码包安装的的服务

                    启动

                        /usr/local/apache2/bin/apachectl    start

                    自启动

                        vi    /etc/rc.local

                              /usr/local/apache2/bin/apachectl    start              

        二、系统默认安装的服务

                1、确定服务分类

                     chkconfig    --list        查看RPM包安装的服务的自启动状态

                        运行级别:0-6

                        0        关机

                        1        单用户模式

                        2        不完全多用户,不包含NFS服务

                        3        完全多用户,字符界面

                        4        未分配

                        5        图形界面

                        6        重启                           

                        

                        init    0        关机

                        init    6        重启

            







置顶
【原创】 Linux IP配置
06 03 2021

三、Linux IP地址配置

一、IP地址配置

        1、配置IP

                执行 setup

                选择网络配置

                图片.png

                选择设备配置

                图片.png

                选择eth0 --> 回车

                图片.png

                配置IP

                图片.png

               Ok-->Save-->Save&Quit-->Quit

                重启网络配置    service    network    restart

        2、启用网卡

                 vi    /etc/sysconfig/network-scripts/ifcfg-eth0

                 ONBOOT=no        修改为        ONBOOT=yes

                 图片.png   

                 重启网络配置    service    network    restart    

        3、修改虚拟机网络连接方式(只针对虚拟机生效)           

               把虚拟机网络连接方式选择桥接

               桥接.png

              

        4、选择桥接到哪一块网卡

                编辑---虚拟网络编辑器---桥接到有线网卡

                图片.png

        5、UUID(唯一识别符)(只针对刻录镜像)

                如果执行以上重启网络,最后一行失败,执行以下

                vi    /etc/sysconfig/network-scripts/ifcfg-eth0

                5.1、删除mac地址行重启一下就会换算UUID ,不要删除UUID  会导致无法连接

                   图片.png

               5.2、删除UUID绑定文件

                rm -rf /etc/udev/rules.d/70-persistent-net.rules

               5.3、重启   reboot  


置顶
【原创】 Linux 软件安装
06 03 2021

四、Linux 软件安装

一、软件包安装

        服务器安装原则:最小化安装、使用什么软件安装什么、尽量不卸载

        软件包选择原则:

                如果软件安装之后,是给大量客户端提供访问的,建议源码包安装

                如果软件安装之后,是给本机或者少量用户访问,建议二进制包

        1、软件包分类

                1.1 源码包:

                    优点:开源、自由定制、本机编译,所以效率高

                    缺点:编译时间长,一旦报错,很难解决

              1.2 二进制包:(也叫rpm包)    

                  优点:安装速度快,简易

                    缺点:不再开源、自定义性差、软件效率低、依赖性...

                       a包--->b包--->c包                     树形依赖

                       a包--->b包--->c包--->a包         环形依赖

                       库文件依赖      去 http://www.rpmfind.net   找

        2、rpm安装,两种安装方式(手工RPM命令安装和yum在线安装,yum是二进制的在线安装方式)

                2.1 手工RPM命令安装

                    2.1.1 包命名

                        包名-版本号-发布次数-适合linux系统.适合的硬件平台.rpm

                        E16  --->   RHEL6

                        包全名:操作没有安装的软件包,软件包使用包全名  gvfs-fuse-1.4.3-12.el6.i686.rpm(完整名字是包全名)

                        包名:操作的是已经安装的软件包使用包名  gvfs-fuse(英文是包名)

                    2.1.2 依赖性

                    2.1.3 安装

                        rpm -ivh    包全名(绝对路径)

                            -i 安装    -v 显示详细信息    -h 显示进度

                        安装位置:默认位置       rpm安装最好不要指定安装位置(有卸载命令),源码包一定要指定安装位置(源码包没有卸载命令,直接删除安装目录)

                        rpm -Uvh    包全名

                             -U 升级 

                        启动程序:

                                /etc/rc.d/init.d/httpd restart             其他linux启动命令            

                                service httpd restart                          redhat linux转悠命令,其他Linux没有    

                     2.1.4 卸载

                         rpm  -e  包名

                            在生产服务器不管是安装还是卸载都不允许强制,必须正确解决依赖性

                      2.1.5 查询

                            a:查询软件包是否安装

                                rpm    -q    包名    查询包是否安装

                                rpm    -qa    |    grep    httpd       显示所有安装包

                            b:查询包信息

                                rpm    -qi    包名    查询包的信息        -p 未安装的包

                                图片.png

                                rpm    -qip    包全名    查询没有安装包的信息        -i   information

                                图片.png

                            c:查询软件安装位置

                                rpm    -ql    包名    查询包中文件的安装位置           l -->list   列表的意思

                                rpm    -qlp    包全名    查询没有安装的包,如果安装会安装的位置

                             d:查询系统文件属于哪个包  

                                rpm    -qf    系统文件名

                                图片.png   

                      2.1.6 启动httpd服务

                            service    httpd    start|stop|restart|status            RedHat版本专有命令

                            /etc/rc.d/init.d/httpd start                                    标准启动          

                      2.1.7 网页目录

                            /var/www/html

        3、yum在线安装(前提条件能连网)

                3.1 基本命令

                      yum    -y    install    包名                安装            -y 自动回答yes

                      yum    -y    remove    包名              卸载        当它不存在,不要乱卸载,不知道被谁依赖了,卸载一时爽,一直卸载一直爽,linux系统下再装回去一个软件可就要老命了

                      yum    -y    update    包名               升级

                      yum    list                                        查询所有可以安装的包

                3.2 光盘作为yum源

                     图片.png   

                     3.2.1 cd /etc/yum.repos.d/

                      默认网络yum源生效,在本机不能连网的时候让光盘yum源生效,网络yum源改名

                      图片.png     

                    3.2.2 mount /dev/sr0    /mnt/cdrom

                    

                    3.2.3  vi    /etc/yum.repos.d/

                              baseurl=file:///mnt/cdrom/                指定yum源位置

                              enabled=1                                          yum源文件生效

                              gpgcheck=1                                        rpm验证不生效

                              图片.png  

                             本地光盘yum源起作用

                              图片.png

                              图片.png  

                              pkill    -9    yum-updatesd                  如果yum报错正在升级,执行此命令,强制杀死升级进程

                              yum    -y    install    gcc                     (gcc是C语言编译器,不装gcc,源码包不能安装,并且安装gcc只能rpm方式安装)           

        4、源码包安装

                问题1:是否可以在一台电脑中既安装RPM包Apache,又安装源码包Apache?

                答:可以,安装位置不一样,RPM包默认安装位置,源码包手工指定安装位置,一般    /usr/local/apache2/,只能启动一个80端口。

                问题2:源码包和RPM包如何选择?

                答:如果服务对大量客户端提供访问,建议用源码包,如果服务只给少数人访问,建议RPM包

                问题3:源码包从哪里来?

                答:官方网站下载

                问题3:如何把windows文件拷贝到linux系统中?

                答:1、远程传输工具winscp或者一些其他工具传输到linux

            4.1 使用传输工具把源码包从windows传输到linux系统

            4.2 安装

                4.2.1 解压

                4.2.2 cd    到解压目录

                图片.png

                4.2.3 查看安装文档

                    INSTALL    README

                4.2.4 编译前的装备

                    ./configure  --prefix=/usr/local/apache2

                    功能:

                        1.检测系统环境        生成Makefile

                        2.定义软件选项   

                 图片.png             

                4.2.5 编译  make    clean

                    make

                4.2.6 编译安装 (在这一步之前报错只需要执行make clean就行,这一步报错需要make clean, 并且删除apache2目录重来)

                    make  install

                    报错判断:

                    第一:安装过程是否停止

                    第二:注意 error    warning    no    等错误报警     

             4.3 启动

                    /usr/local/apache2/bin/apachectl    start    

             4.4 删除

                    直接删除安装目录

                

                    RPM包和源码包的区别:

                            启动:

                                RPM包:service    httpd    start|stop|resrart

                                               /etc/rc.d/init.d/httpd start 

                                源码包: /usr/local/apache2/bin/apachectl    start

                            网页:

                                RPM包: /var/www/html/

                                源码包: /usr/local/apache2/logs/

         5.其他

                5.1 date    查看系统时间

                 图片.png

               date    -s    20130310        设定日期

               date    -s    16:20:00          设定时间

               5.2 du -sh 目录名        统计目录大小(统计的文件大小是准确的,包括垃圾文件、缓存等)

                        -s    总和

                        -h    习惯单位

                   图片.png

                 5.3 df    -h     统计分区大小 (统计的分区剩余空间是准确的,统计硬盘容量)

                




置顶
【原创】 Vi编辑器
05 03 2021

二、Vi编辑器使用

一、Vi编辑器简介

        1、vim(vi增强版本)        全屏幕纯文本编辑器(只能写文字,写字符)

            alias   起别名,临时生效,重启会消失

            图片.png

            vi    /root/.bashrc            环境变量配置文件

                   alias    vi='vim'  

二、使用vim

        1、vi模式

                vim    文件名

             图片.png

     按一个字母a,光标会向后面退一格,进入到插入模式,按ESC退出插入模式;按一个字母i,光标在原来位置;按一个字母o,会换到下一行

     命令--->输入    a追加,i:插入,o:打开(会向下换一行)

     命令--->末行    :w(保存)    :q(不保存退出)    :wq(保存退出)    !强制    :q!(任何用户都可以使用)    :wq!(只有root用户才可以使用)       

   2、命令模式操作

    2.1、光标移动   hjkl   (依次左、下、上、右)  

                 :n移动到第几行

                 图片.png 

               

                gg    两个小写的'g'移动到整个文件首

                G     大写'G'移动到整个文件尾

                ^ (shift+6)   或者Home   光标移动到行首

                $ (shift+4)    或者End  光标移动到行尾

              2.2、删除字母

      x删除单个字母,nx删除n个字母

     2.3、删除整行、剪切

      dd删除单行

       ndd删除多行

      p 小p粘贴到光标后面

       P(英文状态shift+p) 大P粘贴到光标前面

      图片.png  

      dG从光标所在删除到文件尾 (删除之后u撤销) 

     2.4、复制

      yy     复制单行 

      nyy    复制多行

     2.5、撤销     

       u    撤销

      ctrl+r    反撤销                 

     2.6、显示行号

      :set nu     显示行号

       :set nonu    不显示行号  

     2.7、颜色开关

      :syntax off     关闭颜色

      :syntax on       打开颜色  

      2.8、显示隐藏符号(非打印字符)

      :set list     显示影藏字符

      :set nolist     关闭隐藏字符

      图片.png

      vi配置文件

      ~/.vimrc    手工建立的vi配置文件

       ~ 登录用的的家目录

      图片.png

      图片.png  

     2.9、查找内容

      /搜索的字符内容      向下查找

      n下一个 下一个     N(shift+n) 上一个 上一个 

      2.10、替换  s

      ^ 行首符  

      :1,10s/lg/leigong/g    替换1行到10行的所有lg为leigong

      :%s/lg/leigong/g      替换整个文件的lg为leigong

      图片.png

        

      图片.png     

      g范围内替换所有,没有加g只替换找到的第一个,后面的就不会管了

      :1,5s/^/#/g        注释1到5行

      :1,5s/^#//g        取消注释

      :1,5s/^/\/\//g       文件头加入//

      图片.png

                                     


置顶
【原创】 Linux常用命令
23 02 2021

一、Linux常用命令

一、linux命令的格式

        1、命令  [选项]  [参数]  (选项是调整命令的功能,参数是这个命令操作的对象)

             ls     -al    anaconda-ks.cfg(参数)  文件、目录、进程可以作为参数

             ls  list    显示目录下内容

             ls  -a       显示所有文件(包含隐藏文件)

             ls  -al      长格式显示所有文件

             ls  -h      文件大小显示为常见大小单位    B   KB  MB

             ls  -d      显示目录本身,而不是里面的子文件

             ls  -i +文件名      显示文件的inode号

             图片.png

             ls  -l     长格式显示 

             -rw-------    1   root    root    1190    08-10 23:37     anaconda-ks.cfg

             第一项:     权限位 

             第二项:     1      引用计数(对没目录来说代表目录下的子目录,对文件没什么毛用)

             第三项:     root       所有者

             第四项:     root    属组

             第五项:     大小

             第六项        最后一次修改时间

             第七项        文件名

   2、提示符 

     [root@localhost src]#

     [当前登录用户@主机名 当前所在目录]#  

     #  超级用户   

     $  普通用户

     用户家目录   管理员家目录 /root      普通用户家目录 /home/用户名

二、目录操作命令

         1、cd    切换所在目录       列:cd /home

       相对路径:参照当前所在目录,进行查找。一定要先确定当前所在目录。    root]#cd  ../usr/local/src

                     绝对路径:cd  /usr/local/src     从根目录开始指定,一级一级递归查找。在任何目录下,都能进入指定位置

                   cd 或者cd  ~       进入当前用户的家目录     超级用户 /root       普通用户 /home/aa/

                   cd  -        进入上次目录

                   cd  ..        进入上一级目录

                   cd  .         进入当前目录

         2、pwd    显示当前所在目录      

         3、linux常见目录 

            /                         根目录

            /bin                    命令保存目录(普通用户就可以读取的命令)

            /boot                  启动目录 ,启动相关文件

            /dev                    设备文件保存目录

            /etc                     配置文件保存目录

            /home                 普通用户的家目录

            /lib                      系统库保存目录

            /mnt                    系统挂载目录

            /media                 挂载目录   

            /root                    超级用户的家目录

            /tmp                     临时目录

            /sbin                    命令保存目录(超级用户才能使用的目录)  

            /proc                    直接写入内存的 (内存沾满之后会死机,重启会消失,不要随便动内存)

            /sys                      直接写入内存的

            /usr                      系统软件资源目录

                  /usr/bin/        系统命令(普通用户)

                  /usr/sbin/       系统命令(超级用户)

            /var                       系统相关文档内容

                  /var/log          系统日志位置

                  /var/spool/mail/    系统默认邮箱位置

                  /var/lib/mysql/       默认安装的musql库文件目录 

          4、建立目录

            mkdir  目录名

            mkdir  -p   11/22/33              递归创建目录 

          5、删除目录

            rmdir         目录名           (只能删除空目录)

            rm             文件名              删除文件

            rm  -rf       目录                (删除文件和目录)  

                   -r        递归 删除目录

                   -f        强制

           6、tree       目录名    显示指定目录下所有内容的目录树

三、文件操作命令

            1、创建空文件或修改文件时间

                touch        文件名

            2、删除文件

                rm  -rf      文件名

                       -r       删除目录

                       -f       强制

             3、cat   文件名        查看文件内容;从头到尾

                  cat  -n   文件名     列出行号

                  空格向下翻页,b向上翻页,q退出 

                  linux本机  shift+PageUp 向上翻页,shift+PageDown 向下翻页 

             4、more     文件名       分屏显示文件内容

             5、head     文件名       显示文件头

                    head  -n  行数     文件名        显示指定文件头几行

                    head  -n  20        test1          显示文件头20行

                    head  -20            test1          显示文件头20行

              6、tail        文件名      显示文件尾

                     tail    -f   文件名          监听文件尾,不退出

                    快捷键

                    ctrl + c    强制终止

                    ctrl + l     清屏

                    ctrl + u    光标所在删除到行首

                    ctrl + y    粘贴删除的内容

                    ctrl + a    光标移动到行首

                    ctrl + e     光标移动到行尾

                7、链接文件(类似于windows的快捷方式)

                    ln  -s  原文件   目标文件     文件名都必须写绝对路径

                    ln  -s  /root/mymulu/test1      /tmp/bols

                    图片.png

                    更改原文件软链接数据也更改,更改软链接原文件数据也一样更改,删除原文件软链接打不开,删除软链接原文件不影响。

                    图片.png   

四、文件和目录都能操作的命令

           1、rm删除        删除文件或目录        

            2、cp复制

                cp     原文件    目标位置

                        -r    复制目录

                        -p    连带文件属性复制

                        -d    若原文件是链接文件,则复制链接属性

                        -a    相当于    -pdr

                cp  -a  /root/mymulu/test2     /tmp/t2

            3、mv     剪切或改名

                    mv    原文件    目标位置

                    mv  /root/mymulu  /tmp/mymulu         剪切

                    mv  /root/mymulu  /root/my1                原文件位置和目标文件位置在同一个目录下就是改名

五、权限管理

            1、权限位 

                -rw-r--r--.     1     root    root     11    Mar 2 13:36      test2

                权限位十位:

                    第一位:文件类型,(-  普通文件;d 目录文件;l  链接文件;c  设备字符文件  )

                    第二位到第十位(共九位权限位)

                    九位    属主权限u(user)      属组权限g(group)        其他人权限o(other)

                     r            读          4

                        w           写             2

                        x            执行          1

                    

                图片.png

            2、chmod     修改权限

                    chmod     u+x    test1        test1文件的属主加上执行权限

                    chmod     u-x    test1

                    chmod     g+w ,o+w    test1

                    chmod     u=rwx    test1

                    chmod     755     test1

                    chmod     644     test1    

                                     777      绝对不允许在服务器给目录赋予777权限   

            3、权限的意义

                    3.1、权限对文件的含义

                        r:读取文件内容                           对应命令: cat    more    head    tail

                        w:编辑、新增、修改文件内容(不包含删除文件内容)    对应命令: vi、echo        

                        x:可执行     对文件来说最高权限是执行权限

                        给hello.sh文件赋予755权限,并且执行它

                        图片.png

                        执行文件两种方式,1、绝对路径方式            2、相对路径方式

                        图片.png

                     3.2、权限对目录的含义

                        r:可以查询目录下文件名            对应命令:ls

                        w:具有修改目录结构的权限。如新建文件和目录,删除此目录下得文件和目录,重命名此目录下得文件和目录,剪切, 对应命令:touch      rm    mv     cp ,对目录来说最高权限是写权限

                        x:可以进入目录       对应命令:cd

                        目录可用权限: (必须要有查看权限和进入目录权限)

                        0        最小权限

                        5        基本权限

                        7        最大权限

            4、属主和属组命令   chown

                    chown      用户名      文件名            改变文件属主

                    chown      user1       aa1                 user1用户必须存在

                    chown      user1:user1     aa1         改变属主的同时改变属组

                    useradd    用户名            添加用户      (在添加用户的时候默认会添加一个和用户名一样的组)

                    passwd     用户名            设定用户密码  

六、帮助命令

               1、man   命令                    查看命令的帮助

                    man   ls

               2、命令  --help     

                    touch     --help         查看命令的常见选项  


七、查找命令

               1、whereis   命令名           查找命令的命令,同时看到帮助文档的位置

                它在哪?

                图片.png

                它是干嘛的

                图片.png

                2、find           搜索命令

                按照“文件名”查找    -name

                find    查找位置    选项            文件名

                find     /               -name        abc                按照文件名查找

                图片.png

                图片.png

                按照“用户”查找    -user

                find    .    -user    root           查找当前目录所有者是root的文件

                find    .    -group    root        查找当前目录所属组是root的文件

                find    /    -nouser                 查找/目录下没有属主的文件

                Linux中没有所有者的文件,以下两种是正常的:

                    1、外来文件(U盘、光盘)

                    2、极少内核产生的文件

                    /proc          /sys          /mnt/cdrom/  除了这三个目录     


                通配符:

                    *        匹配任意内容

                    ?        匹配任意一个内容

                    []        匹配任意一个中括号里面的内容

                正则:

                    *        前一个字符匹配任意多次

                    .         匹配任意一个字符

                    .*        匹配任意内容

                    ?        前一个字符匹配0次或1次

                    []        匹配中括号内任意一个字符

                    通配符:用来匹配查找文件名,通配符是完全匹配,必须一模一样(用来匹配字符串),完全匹配(find查找)

                    正则:    用来匹配文件里的内容,是包含匹配(grep查找)

                按照“文件大小”查找    -size

                -size    按照文件大小查找    +50k,大于50k,-50k,小于50k,50k,等于50k      k(千字节必须小写),M(兆字节必须大写)

       -size       n[cwbkMG](选项)

                  File uses n units of space.  The following suffixes can be used: 文件使用n个空间单位。可以使用以下后缀:

                      ‘b’    for 512-byte blocks (this is the default if no suffix is used)  b是选项默认的,不加单位则按照512字节作为一个数据块搜索

                      ‘c’    for bytes        按照字节搜索

                        图片.png

                      ‘w’    for two-byte words         双字节,按照一个字搜索

                      ‘k’    for Kilobytes (units of 1024 bytes)        “k”表示千字节(1024字节的单位)按照千字节搜索

                      ‘M’    for Megabytes (units of 1048576 bytes) “M”表示兆字节(单位为1048576字节)按照兆字节搜索

                      ‘G’    for Gigabytes (units of 1073741824 bytes)  “G”表示千兆字节(单位为1073741824字节)按照千兆字节搜索              


                     find    .    -size    -1k        在当前目录查找小于1k字节的文件

                    图片.png

            

                    按照“文件类型”查找    -type

                    -type      类型        按照文件类型查找     f:普通文件    d:目录    l:链接文件

                    find     .     -type      f

                    find     .     -type      d

                    按照“权限”查找    -perm

                    find    .    -perm    644       

                    按照“文件名不区分大小写”查找     -iname    

                    find    .    -iname   abc

                    图片.png 

                    按照“i接点”查找    -inum

                    find    .    -inum   786119    知道i节点去查找文件名

                    图片.png    

                    ls -i   知道文件名去查找i节点

                    图片.png

                    按照“修改时间”查找    -mtime

                    -10,10天内;+10,10天前;10,第10天

                    在查找出的结果中,直接进行命令操作

                    图片.png

                    长格式显示1天内m2目录下面创建的文件和目录

                    图片.png

                 3、grep    "字符串"    文件名        查找符合条件的字串   

                        grep    "root"    /etc/passwd

                        grep    -v    "root"    /etc/passwd         -v反向选择(取反),在/etc/passwd  中不存在root 字符的

                4管道符 

                        命令1     |    命令2        命令1的执行结果作为命令2的执行条件  (管道符的作用和-exec的作用一模一样,find命令不支持管道符,所以专门开发了-exec命令)

                        只要加了管道符,不论前面是文件还是内容,全都当做文件内容来处理,使用grep搜索查找

                        netstat -an | grep ESTABLISHED | wc -l       统计正在连接服务器的网络连接数量

                        补充命令:

                        netstat        查看网络状态的命令

                                -t        查看tcp端口   (tcp通信,需要进行三步,A问B你在吗,B答复A我在,A再给B回复我要发数据了,可靠)

                                -u        查看udp端口    (udp,A直接发数据给B,速度快)

                                -l         监听                         

                                -n        以IP和端口号显示,不用域名和服务名显示

                        netstat        -tuln        查看本机开启的服务

                        图片.png

                        netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n           按照连接数量,统计哪个ip地址连接数量多,可以用来屏蔽排除非法攻击

八、压缩和解压缩

               1、linux可以识别的常见压缩格式

                .gz                .bz2

                2、常见的压缩和打包命令

                .tar.gz (压缩性能相对较差,但是速度更快)          .tar.bz2  (算法先进,压缩出来结果更小,但是更占用时间)

                linux不靠扩展名区分文件类型,而是靠权限,建议linux系统下压缩包严格区分扩展名

                tar    -zcvf    压缩文件名    源文件

                tar    -zcvf    aa.tar.gz        aa

                         -z        识别.gz格式

                         -j         识别.bz2格式

                         -c        压缩

                         -x        解压缩

                         -v        显示压缩过程

                         -f        指定压缩包名          

                             -t        只查看不解压

                查看不解包

                tar    -ztvf    aa.tar.gz            查看不解包

                tar    -jtvf    aa.tar.bz2

                指定到解压位置

                tar    -jxvf    aa.tar.bz2    -C    /tmp/            

九、关闭和重启命令

               服务器绝对不允许关机,只能重启,并且服务器应该定时重启,保证服务器状态归零

               1、shutdown    -h    now        没有特殊情况,禁止使用此命令

                    shutdown    -h                关机

                    shutdown    -r    now      立即重启     (shutdown     -r  重启,最安全的重启命令,会保存正在运行的服务然后再重启)     

                    shutdown    -r    16:00    16:00重启       -r(reboot)

                    windows设置关机,shutdown    -s    -t    200(秒)

                2、reboot    重启

十、挂载命令

               linux所有存储设备都必须挂载使用,包括硬盘

                挂载:给你的分区找到一个硬件名,创建一个目录,把它连起来

                /dev/sr0<------->cdrom

               1、mount                挂载

                mount    -t    文件系统    设备描述文件    挂载点(已经存在的空目录)

                mount    -t    iso9660     /dev/sr0            /mnt/cdrom/         默认挂载选项

                mount     /dev/sr0         /mnt/cdrom/                                   简写挂载

                光盘挂载

                /dev/sda1                第一个scsi硬盘的第一个分区

                /dev/cdrom            光盘

                /dev/hdc                 光盘        centos5.5

                /dev/sr0                  光盘        centos6.x

                图片.png

                /dev/sr0   设备文件名      /mnt/cdrom/ 才是盘符

                

                mount直接回车,查看当前已经挂载的设备


                2、umount              卸载

                    umount    /mnt/cdrom        强调:退出挂载目录,才能卸载

十一、网络命令

               1、ping    测试网络连通性

                    ping    -c    次数    ip        探测网络通畅

                    图片.png

                2、ifconfig        查询本机网络信息

                    图片.png

                

                 Linux脚本中 #是注释  唯独一句  #!/bin/bsah 不是注释, 标注下面是shell语句开始...


十二、centOs7防火墙操作命令

        1、防火墙开启、关闭、禁用

            (1)设置开机启用防火墙:systemctl enable firewalld.service

            (2)设置开机禁用防火墙:systemctl disable firewalld.service

            (3)启动防火墙:systemctl start firewalld

            (4)关闭防火墙:systemctl stop firewalld

            (5)检查防火墙状态:systemctl status firewalld

        2、使用firewall-cmd 配置端口

            (1)查看防火墙状态:firewall-cmd --state

            (2)重新加载配置:firewall-cmd --reload

            (3)查看开放的端口:firewall-cmd --list-ports

            (4)开启防火墙端口:firewall-cmd --zone=public --add-port=9200/tcp --permanent

        命令含义:

            –zone #作用域

            –add-port=9200/tcp #添加端口,格式为:端口/通讯协议

            –permanent #永久生效,没有此参数重启后失效

        注意:添加端口后,必须用命令firewall-cmd --reload重新加载一遍才会生效

            (5)关闭防火墙端口:firewall-cmd --zone=public --remove-port=9200/tcp --permanent


【原创】 投资一家公司多维度思考
15 11 2025

投资一家公司多维度思考

        投资企业前的挥杆分析

        1、天山铝业

        ① 文化(口号)          企业文化合格√

        企业价值观:激情 高效 关爱     

        工作重心:安全环保       

        公司使命:  让地球更加轻盈,更美丽  

        企业愿景:共建长青一流企业

        经营理念:社会、企业、个人的目标、责任、利益相统一

        ② 行动       

        待观察,途径:官网、公众号、新闻、社会活动等等...

        ③ 护城河:品牌一般、技术在行业中中规中矩、铝锭产品在行业中不具有差异化          护城河一般  ×

        ④ 商业模式:能产生持续充沛的自由现金流,铝锭价格并非单纯由期货决定,而是形成了一个以期货市场为“定价中枢”和“指挥棒”,现货市场为“基本面验证者”的紧密联动体系(铝锭价格主导力量:期货交易所    重要参与者影响:大型生产商、大型贸易商、终端消费、金融机构与投资者、政府与监管机构、国际环境因素、国际金属价格趋势等),且天山铝业属于重资产类型企业,具有持续资本性开支来维持在行业中的地位        商业模式一般  ×

        ⑤ 估值  (前提是选择一个护城河优秀、商业模式好的企业,上述天山企业只能说一般)       估值5年内翻倍,估值一般 ×      

        思路: 根据2025年三季报作为参考,毛估估:

        a:确定当前自由现金流

        经营活动产生的现金流净额(所有者盈余):48.5Y

        资本性支出:11.4Y

        自由现金流:经营活动产生的现金流净额 -  资本性支出    48.5-11.4 = 37.1Y

        b:估算一个保守增长率      未来5年,给一个6%

        c:估算第一阶段现金流现值

        1年后的现金流 ≈ 37.1* (1.06)^1 ≈ 39.32亿元。

        2年后的现金流 ≈ 37.1* (1.06)^2 ≈ 41.68亿元。

        3年后的现金流 ≈ 37.1* (1.06)^3 ≈ 44.18亿元。

        4年后的现金流 ≈ 37.1* (1.06)^4 ≈ 46.83亿元。

        5年后的现金流 ≈ 37.1* (1.06)^5 ≈ 49.64亿元。

        d:确定折现率: 长期国债利率 2.3% ~~2.5%, 我们取一个5%--10%的区间值  5%作为折现率

        e:估算永续价值

            ① 假设永续价值为0

            ② 永续价值 = 第N年的自由现金流 / 折现率     49.64 / 0.05  ≈ 992.8

             ③ 毛估估总内在价值 = 永续价值 + 第一阶段现金流现值     992.8 + 39+41+44+46+49   ≈  1211.8 Y

结论:天山铝业目前市值650Y,5年内保持年6%以上的净利润增长率,5年内的某个时间节点有几率市值达到1200Y,  通过以上5个方面要素分析,天山铝业  1 √    3×   1待观察不确定, 不是最佳投资选择,继续分析其他目标

        

        

【原创】 十七、十五五及未来5-10年风口行业
02 11 2025

十五五及未来5-10年风口行业

        一、十五五规划风口行业总结

        1、待补充



        二、未来5-10年风口行业

        1、银发经济与大健康      (养老护理、高端养老社区、陪护机器人,60岁以上人口近3亿,健康监测设备需求激增)    

        2、集成电路/芯片   加速迭代            

        3、人工智能      加速迭代,融合应用  (细分领域:AI芯片、端侧AI硬件设备、垂直领域大模型、行业应用软件)     

        4、量子科技

        5、生物制造/脑机接口

        6、氢能/核聚变能          

        7、第六代移动通信

        8、高端制造硬科技       (细分领域:人形机器人、高阶智驾)           

        9、低空经济与商业航天       (空域开放,低空经济商业化    细分领域:  无人机物流、eVTOL载人出行、卫星互联网)      

        10、数字经济与数据要素     

【原创】 基础知识
13 02 2025

基础知识

        一、未来十年贬值最快的是什么

        ①大学文凭(学历),就业市场学历通胀。

        ②非核心城市房产,人口老龄化+生育率下降,三四线城市空置率攀升,房价持续下跌

        ③传统燃油汽车

        ④现金、存款,全球低利率环境延续,存款利率持续下行; 人民币国际化进程中可能面临汇率波动风险,进一步影响储蓄价值。

        ⑤奢侈品

        ⑥A股股票,新股发行速度过快导致资金分流,估值泡沫风险高;投资者结构以散户为主,投机性强,长期投资价值不足。

        ⑦传统世俗文化观念,年轻人对婚姻、家庭的传统观念淡化,晚婚、不婚、丁克等;节日习俗、宗族观念逐渐被个性化生活方式取代。

        ⑧低技能重复性工作岗位,自动化和AI技术普及,工厂普通岗位需求锐减。

        ⑨中产阶级身份象征,象征地位的物品(名牌包、高档轿车等)大众化而失去独特性。

        ①①燃油车相关产业,如加油站、零部件等。









【原创】 莫生气
15 07 2024

莫生气

        2024-7-15笔记:

        ①一切的不快皆源于心态,有什么样的心态,就会有什么样的生活。

        ②心态是快乐的,我们自然就是快乐的;如果满脑子忧郁的想法,就会显得十分悲观。

        ③令自己灰心丧气的不是所遭遇的各种状况,而是你对这些状况的想法。

        ④很多时候快乐其实是内心的富足,与金$无关。

        ⑤想活得轻松一些,就要凡事豁达一点、洒脱一点,不必把一点点小惠小利看得过重,而要达到这种超脱境界,关键是寻求心灵的满足。

        2024-7-16笔记:

        ①乐观的人并不是生活上万事如意,而是他们明白,能够战胜困难的永远不会是沮丧忧愁,而是勇敢与微笑。

        ②逃出自筑的精神牢狱,寻找满天繁星。

        ③快乐源自于一种成就感,一种自我超越的胜利。

        ④生命是一个自然的过程,生的必然和死的必然都是一样的。春天,百花盛开,树木抽芽,到了秋天,树叶飘落,乃至草木枯萎,这就是无常相。

        ⑤忘掉过往,它会遮蔽未来。

        ⑥要想成为一个幸福的人,必须先敞开你的心扉。

        ⑦无论遭遇什么困难,只要你不顾一切的去拥抱生活、寻求快乐就能从痛苦中解脱。也只有乐观向上的人,才能理解和享受生活。

        ⑧事实上,幸福是无所不在的,“保持高度的幽默感”是关键之一。

        2024-7-17笔记:

        ①人之所以活得累,是因为放不下架子,撕不开面子,解不开情结。

        ②不去勉强别人,也不强求自己。

        ③既不感叹命运也不抱怨时代,当不了大树就当小草,当不了太阳就当星星,当不了江河就当小溪。

        ④世间没有什么东西是恒久不变的。

        ⑤一个人的智力有问题,是次品;一个人的灵魂有问题,就是危险品。

        ⑥你是积极的,世界就是积极的。反之亦然,这就是观念的力量。

        ⑦只有当你心中的世界模式发生了改变时,现实的世界才会随之改变,使你适应并与之达到和谐。

        ⑧如果我们用一种忧郁的心态面对人生,那么,人生就会成为一种折磨和煎熬。

        2024-7-19笔记:

        ①生气是人生幸福的最大障碍之一,是事业成功的拦路虎。

        ②通常,易发脾气的人与人相处尝尝出言不逊,不顾他人的自尊心与个性特点,一味强求别人与自己保持统一,这样的人很难获得和谐的人际关系。

        ③动不动就生气的人,往往什么事都办不成,因为满怀怒气,必然丧失理智。

        ④遇到麻烦不要抱怨也不要责怪他人,带着神么样的态度去处理问题就注定了会得到什么样的结果,控制好情绪让自己平静,努力想最优的解决办法去处理问题。

        2024-7-27笔记:

        ①托人办事,首先礼貌问候、寒暄,如果合适,适当礼物。

        ②在①得到良好回应后再引出自己的需求,需要的帮忙。

        2024-8-8笔记:

        ①安身立命谨记16字:藏锋、隐智、戒欲、省身、求实、慎言、节情、向善

        藏锋:才华不外露。

        隐智:不露才智。

        戒欲:戒欲是指对欲望或冲动的抑制或控制,通常用于描述对一些负面或有害的欲望或冲动进行抑制或限制的过程。

        省身:字面意思是检查自身过失,克制自己非分之想。在更深层次的理解上,省身强调的是在日常生活中随时随地对自身行为进行反省与自律的一种状态。这一概念源于‌儒家思想,特别是‌曾子所说的“吾日三省吾身”,即每天多次自我反省。省身不仅是自我检查行为的对错,更是对内在思想的自省和外在行为的检点,是修身养德的基础。

        求实:指讲求实际,客观地或冷静地观察以求得对客观实际的正确认识。这一概念强调了在实际行动和决策中基于事实和实际情况的必要性。

        慎言:说话非常谨慎。

        节情:学会控制情感,避免过度悲伤,保持平静和乐观。它强调在情感的表达上要适度,既不压抑也不放纵,以实现内心的和谐与平衡。节情不仅是对内心情感的深思熟虑和精准把控,更是一种高超的自我调控艺术,旨在增进人与人之间的理解和沟通。‌

        向善:字面上理解,‌就是向着善良的方向行动。‌它强调的是一种积极向上的行为准则,‌即通过自己的行为去帮助他人,‌做对他人有益的事情。‌这种行为不仅体现了个人对他人的关爱和帮助,‌也反映了个人内心的善良和积极向上的态度。‌

        2024-8-19笔记:

        ①做人第1点:坚持原则,坚持底线,坚持初衷。《道德经》中有言“持而盈之,不如其已;揣而锐之,不可长保。金玉满堂,莫之能守;富贵而骄,自遗其咎。功成身退,天之道也。” 做人不能抛弃、不能践踏信用和原则。

        ②做人第2点:一定要懂礼貌,学习礼仪,学习历史文化。

        ③做人第3点:看书,坚持学习,有一句话是那么说的,一个人如果长期不看书,那么他的人生观将由他身边的人决定。


【原创】 父母的寄托
30 05 2024

父母的寄托

        青春期以及年轻时候我很倔强,很不听话,现在年龄来到三十多岁,老妈分享一些视频给我,看完我也会哭,她头发已经花白,60岁左右的人了,而我也马上进入中年,且一无所有,每当看到这类的视频感触颇深。感触可能会在短暂的瞬间触动很深,过后可能逐渐被日复一日的忙碌磨灭。感谢各位作者老师,我搬来了你们的金石良言,时常来接受灵魂的触动。

    五六年的码农生涯,变得越来越自闭,不善于交流和表达感情,就记在这里吧,没地方表达。

    看多了几次下面两个视频,眼泪鼻涕流了十几分钟没停止       ----2024-5-30 23:39:18

    

    ① 孩子,是父母唯一的寄托。

    ② 我不能走,我走了以后我的孩子怎么办。

    ③ 不要等到父母不在的时候再后悔,为时已晚,人活着的时候不孝顺,等到父母没了,去坟前烧香烧纸那都是骗人的。

    ④ 不能像个废物一样活着,不允许,不管现在身处在什么样的群体阶层,坚持学习坚持看书,不看书,价值观将由身边的人决定。


----------分割线----------


【原创】 十一、揭开伤疤
06 04 2024

回顾错误

        一、揭开伤疤或许很痛,但同样刻骨铭心!!!

        1、四川CH,没有散户不敢接的票,也没有散户不敢割的肉,刚入市第一年,多么畜生的BS点(追涨杀跌)

          

        2、京东F,有什么高位是散户不敢接的,拿得受不了了割就是,佛祖还割肉喂鹰呢,我割这点算什么(瞎几把追瞎几把割)

        京东方.jpg

        3、未名YY,没有哪种炸了的板是我等韭菜接不了的,也没有哪坨肉是本韭菜割不动的~(无脑打板冲最高点)

          

        4、山煤GJ,厉害啊,产业链就需要多认识本菜这样的朋友,抹泪跪谢散韭抬主力出门(无脑追高割肉)

        山煤国际.jpg

        5、金财HL,有什么样的高度什么样的价格是本韭菜接不了的啊?你们主力接得了的我要接,你们主力接不了的我也要接,这便是本韭菜!!!(无脑追高割肉)

          

        6、三峡NY,还是那句话,什么样的新股我不敢打,什么样的价格我不敢接?(无脑打新割肉)

        三峡能源.jpg

        7、沃顿KJ,我,某某菜要半路接你,能奈我何?(无脑打板割肉)

        沃顿科技.jpg

        8、百川GF、六国HG、和邦SW,同一年,差不多同一时间段,买进了拿不住,错失3个翻倍股(不懂看板块热度、市场情绪,瞎几把BS,前一天买第二天就必须得卖,不操作手踏马不好过?而且,下跌调整过后一段时间再也不去关注,再次起阳线走趋势连鸟都不去鸟它???)

          

        和邦生物.jpg

        9、中远HK,追高割肉,追高割肉(瞎几把乱追高,而且还没有体系,没有止损点)

          

        10、晶方KJ,什么高度我不能接啊, 什么地板我不敢割啊(追涨杀跌不说,踏马不涨的最高的时候不进,不跌到最低的时候不割)

        晶方科技.jpg

        11、中国DX,管你什么样的新股,本菜哪只不敢进,管你直线拉多少度,90度我都照样接(傻比比的全仓单吊超级大盘子股,第二天开始连续两天闷杀出不来,贼心当时这么幻想的,老子吃一个涨停,一天几千上万块,两三个涨停,老子直接起飞当半年工资,还有谁?)

        中国电信.jpg

        11、大金ZG,(涨势初期我唯唯诺诺,涨势高潮见顶我重拳出击;不涨到最高点我绝不接盘,这就是本菜!!!)

        大金重工.jpg

        12、ST澄星(胆儿肥了,打板追高接力已经满足不了刺激,还要学别个玩ST是吧)

        ST晨星.jpg

        13、大西洋,(有什么样的烂板是本韭不敢买的啊,有什么样的主力是我抬不出去的吗)

        大西洋1.jpg

        14、ST金山  (什么样的产业链群是我不敢加的,什么样的产业链“老师”是我不敢相信的啊,什么样的出货点我不敢接?什么样的地板我不敢割?这便是本菜“助人为乐”的崇高精神)

          

        15、湖南TY,(不是最高点的筹码老子看都不看,不是跌停板的位置老子割都不

          

        16、华兰SW(下跌横盘震荡阶段我唯唯诺诺,涨了三波眼红我重拳出击)

        华兰生物.jpg

        17、圣龙GF,(下跌横盘震荡阶段我唯唯诺诺,涨了三波眼红我重拳出击,下跌不止损我死扛到底,扛不住了亏损三十个点我“不吝割爱”,这便是本菜实力的进一步提升

        圣龙股份.jpg

        18、信达ZQ,(盈利走了你还要信别个吹嘘这股一定能站上多少多少,还要冲进来,进来就遇到1月份,舒服了吧;还死扛不止损,不割肉,-10%止损点真踏马就是摆设,那还要体系干锤子吗?天天喊的知行合一就是左边耳朵进右边耳朵出呗...... 还有,证券这种叼毛板块从没挣过还要进来,避开板块也是说来玩的对吗?)

        信达证券.jpg


        19、2024-11-1犯错,在2024-10-31中小盘尾盘集中炸板的情况下,2024-11-1早盘本来只亏800的情况下,贪心,梦想还能多赚,就一直稳起等上涨, 最后亏到3000忍不住割肉;割肉后犯下第二次错误,幻想当天11-1号本月开门,一定要整个开门红,割肉完以后,胡乱瞎几把乱冲票, 满仓位又买了3只中小盘股票,并且打满仓位,其贪欲   盈利的心之重,B计划外的票,一切的计划都被贪欲吞噬。





【原创】 HTTP状态码
27 09 2022

HTTP状态码


一、常用状态码

        1. 100 开头状态码

        image.png

        2. 200 开头状态码

        image.png

        image.png

        3. 300 开头状态码

        image.png

        image.png

        4. 400 开头状态码

        image.png

        5. 500 开头状态码

        image.png

        image.png

        

            


【原创】 Redis应用
23 09 2022

Reids + PHP应用


一、消息队列原理、概念

            1.1 消息队列概念

                a、队列结构的中间件

                b、消息放入后不需要立即处理

                c、由订阅者/消费者按照顺序处理

            1.2 核心结构

                image.png

            1.3 应用场景

                冗余:比如订单系统,需要严格的做数据转换和记录,消息队列可以持久化的把这些信息存储在消息队列中

                解耦:比如两套系统,彼此独立

                流量削峰:秒杀和抢购,配合缓存来使用消息队列

                异步通信:

                排序保证:

            1.4 常见队列实现优缺点

                队列介质:

                image.png

            1.5 消息处理触发机制

                image.png

二、解耦案例-队列处理订单系统和配送系统

            2.1 架构设计

                image.png

            2.2 程序流程

                image.png

三、流量削峰案例 - Redis的List类型实现秒杀

            3.1 架构设计

                image.png

            3.2 代码设计

                image.png

                用户秒杀的代码

                image.png

                image.png

                模拟秒杀生成的uid参数

                image.png

                读取redis队列,数据写进数据库的代码

                image.png

                image.png

                

四、RabbitMQ - 更专业的消息系统实现方案

            4.1 RabbitMQ的架构和原理

            image.png

            4.2 RabbitMQ安装

                image.png

            4.3 Work Queue

                image.png

                

            

五、PHP秒杀系统整体设计

            5.1 本质

                高并发、高可用

            5.2 原理知识介绍

            减而治之:

                a、CND原理

                b、nginx限流

                c、异步队列

            分而治之:

                a、nginx负载均衡

            5.3 特征与难点分析

                特征:

                    a、写强一致性:卖出的商品、计数的数量一致

                    b、读弱一致性:比如12306抢票的时候确实看到有票,下单的时候却没了

                难点:

                    a、极致性能的实现

                    b、高可用的保证

            5.4 秒杀系统核心实现

                1. 极致性能的读服务实现:

                    a场景、订单详情页读取,通过CDN加速方式减轻服务器压力

                    b场景、实时读取总库存

                2. 极致性能的写服务实现:

                    a场景:扣库存

                3. 极致性能的排队进度查询实现

                    比如12306抢票,可能会有一个排队的进度,用户频繁去查询还剩多少分钟,这么一个服务

                4. 链路流量如何优化

                    比如流量到达LVS层、接入层、service层

            5.5 兜底-高可用

                1. 高可用的标准

                2. 请求链路中每层高可用的实现原理

                3. 限流、一键降级、自动降级实现

            5.6 接口压力测试

                平时使用最多的ab压测工具,通过 “Requests per second:”这一项数据值分析接口和机器性能状态

            5.7 限流

                1. nginx限流配置

                    image.png

                    区别:上面一个限制并发数,下面一个限制单个ip请求数

                    image.png

                2. 限流算法介绍

                    a、令牌桶算法

                    image.png

                    image.png

                    image.png

                    b、漏桶算法

                    image.png

                image.png

            5.8 CND介绍

                image.png

                提高读源站性能一大利器

                CND原理:

                image.png

                image.png

                CDN - 普通域名访问

                image.png

                CDN - DNS解析原理

                image.png

                image.png

                image.png

                image.png

                注意:不同地域的客户端访问同一个域名的时候,拿到的CND地址是不一样的,基本是距离客户端比较近的CDN服务器地址,通过这样的方式来实现一定的加速;而CDN服务器也会把源站上的内容做一定时间的缓存,通过这样的方式来降低源服务的qps,提高读服务性能

            5.9 大型网站架构

            image.png


            5.10 秒杀系统使用场景

                image.png

                5.10.1 秒杀系统 - 特点介绍

                a、抢购人数远远多于库存,读写并发极大

                b、库存少,有效写少

                c、写强一致性,商品不能超卖,也就是说库存减少量与创建订单量必须一致的

                d、读一致性要求并不高

                

                5.10.2 秒杀系统 - 难点

                稳定性难:

                    a、高并发下,某个小依赖可能直接造成雪崩

                    b、流量预期难精确,过高也会造成雪崩

                    c、分布式集群,机器多,出故障的概率高

                准确性难:

                    a、库存、抢购成功数、创建订单数之间一致性

                高性能难:

                    a、有限成本下需要做到极致的性能

                5.10.3 秒杀系统 - 架构原则

                稳定性:

                 image.png

                高性能:

                    image.png

                5.11 秒杀服务核心实现

                5.11.1 该怎样去设计?

                image.png

                基本需求:

                image.png

                基本需求 - 场景举例:

                image.png

                基本需求 - 扣库存方案:

                image.png

                预扣库存方案实现:

                image.png

                极高并发下怎么做到单服务极致性能:

                image.png

                I/O主要包含:

                image.png

                无I/O怎么做?

                image.png

                普通下单业务实现:

                image.png

                去I/O后的业务实现:

                image.png

                并发量过大单服务还是扛不住怎么办?

                image.png

                本地减库存,集群机器挂了怎么办?怎么保证不少卖?

                image.png

                单服务扣库存实现:

                1、初始化库存到本地库存

                2、本地减库存,成功则进行统一减库存,失败则返回

                3、统一减库存成功则写入mysql,异步创建订单

                4、告知用户抢购成功

                

                创建订单、支付订单服务:

                image.png

                基本需求 - 读取商品信息:

                image.png

                

                

                

                

                




                

                    




【原创】 电脑装杯小技巧
16 09 2022

常用装杯小技巧

    装杯技巧记录

    1、快速回到桌面:

    Windows + D

    2、一键锁屏:

    Windows + L

    3、快速打开文件资源管理器:

    Windows + E

    4、快速放大文字或者图片:

    Windows + “+”

    5、快速缩小文字或者图片:

    Windows + “-”

    6、隐藏打开的窗口文件:

    Windows + M

    7、快速打开任务管理器:

    Ctrl + Shift + Esc

    8、快速打开Windows设置:

    Windows + I

    9、恢复上一步操作:

    Windows + Y














【原创】 二、PC端工具快捷键
17 07 2022

通达信快捷键使用

        1、第一类  数字类

        03回车,调出沪指

        04回车,调出深成指

        06回车,调出自选股

        09回车,画线工具

        15回车,板块指数

        45回车,显示未回补跳空缺口

        48回车,显示最近浏览的股

        50回车,上证50走势

        60回车,当天的实时涨跌幅排名

        80 回车,综合排名,查看当天市场跌幅、振幅、涨幅等排名

        880005  涨跌家数


        2、第二类  字母类或者组合类

        Table,关闭/显示均线

        F1,表格形式查看个股每天的情况

        F5,查看分时图

        F6,查看自选股

        F8,切换周期(5分钟、30分钟、日K等)

        F10,查看个股信息

        ctrl+R,个股题材概念、板块信息等

        ctrl+K ,前复权/不复权

        ctrl+L ,显示隐藏行情信息(右边买卖、市值、个股名称等等)


        3、第三类  字符数字组合类

        .400    板块分析-所有版块

        .403    区间涨跌幅

        .404    区间换手排名

        .403    区间涨跌幅

        .5/.501        分时走势图

        .502    分时成交明细

        .503    分价表

        

        4、第四类  K线类

        平移K线    分析图主图中左键拖拽屏幕底部时间标尺

        压缩K线    分析图主图中右键拖拽屏幕底部时间标尺

        缩放K线    分析图中Ctrl + 鼠标滚轮


【原创】 Redis入门、第二部分
09 06 2022

Reids数据库基础知识


一、Redis高级

            1.1 通用命令

            1.1.1、key通用指令

            key特征:key是一个字符串,通过key获取redis中保存的数据

            key应该设计哪些操作?

            对于key自身的状态相关操作,例如:删除,判定存在,获取类型等

            对于key有效性相关操作,例如:有效期设定,判定是否有效,有效状态的切换等

            对于key快速查询操作,例如:按指定策略查询key

            

            key基本操作:

            a、删除指定key:del  key

            image.png

            b、获取key是否存在:exists  key 

            image.png

            c、获取key的类型:type  key

            image.png


            key扩展操作(时效性):

            a、为指定key设置有效期:expire  key  seconds

            image.png

            b、为指定key设置有效期:pexpire  key  milliseconds

            image.png

            c、为指定key设置有效期:expireat   key  timestamp

            image.png

            d、为指定key设置有效期:pexpireat   key  milliseconds-timestamp

            e、获取key的有效时间:ttl  key

            image.png

            ttl获取key过期时间,如果一个key不存在,则返回-2;如果一个key存在,则返回-1;如果一个设置了有效期,则返回剩余有效时间

            f、获取key的有效时间:pttl  key

            image.png

            g、切换key从时效性转换为永久性:persist  key

            image.png


            key通用操作:

            a、查询key:keys  pattern(匹配的语法格式)

            image.png

            image.png

            image.png

            image.png


            key其他操作:

            a、为key改名:rename  key  newkey

            image.png

            b、如果key不存在则为key改名:renamenx  key  newkey

            image.png

            image.png

            c、对所有key排序,只是排了序,没有动原来数据:sort  key  

            image.png


            1.2 数据库通用指令

            1.2.1、看如下问题

            image.png

            1.2.2、db基本操作

            a、切换数据库:select  index

            image.png

            b、控制台打印:echo   xxx

            image.png

            c、测试客户端与服务端连通性:ping

            image.png

            d、移动数据:move  key  db

            image.png

            数据清除操作(谨慎、小心操作):

            e、清除当前数据库:flushdb

            f、清除所有数据库:flushall  不要用这个指令,0-15号库数据全部干掉...

            g、查看数据容量:dbsize

            image.png


二、Redis持久化

            2.1 意外的断电

            image.png

            2.2 自动备份

            image.png

            2.3 什么是持久化

            利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化

            2.4 为什么要持久化

            防止数据的意外丢失,确保数据的安全性

            2.5 持久化过程保存什么

            image.png

            2.6 持久化方案一 ,RDB启动方式--save指令

            image.png

            持久化的命令:save

            作用:手动执行一次,保存一次

            image.png

            2.6.1 RDB相关配置

            RDB启动方式----save指令相关配置

            image.png

            1、设置dbfilename

            image.png

            2、设置rdbcompression 值为yes

            image.png


            2.6.2 数据恢复过程演示

            image.png

            杀掉进程后再启动,上图的3420进程,redis又重新运行

            image.png

            数据已经恢复

            image.png

            2.6.3 save指令工作原理

            1、假如4个指令都要执行,并且按照客户端1--4的顺序先后到达并执行

            image.png

            2、到达以后假如是下面的指令排序

            image.png

            3、指令执行

            image.png

            4、save指令有可能造成阻塞,拉低服务器性能,线上环境不建议使用save指令

            image.png

            

            2.7 持久化方案二 ,RDB启动方式--bgsave指令

            数据量过大,单线程方式造成效率过低如何处理?

            image.png

            2.7.1 持久化命令

            指令:bgsave

            作用:手动启动后台保存操作,但不是立即执行

            操作:

            image.png

            执行bgsave命令前

            image.png

            执行bgsave命令后,文件大小已经变了

            image.png

            查看文件内容,已经增加了addr值chengdu

            image.png

            2.7.2 bgsave指令工作原理

            1、下达指令

            image.png

            2、调用linux的fork函数,生成子进程,由子进程去完成

            image.png

            在日志文件去查看这个过程

            image.png

            注意:bgsave命令是针对save命令阻塞问题做的优化,save命令是立马执行,并且加入到任务执行序列中,bgsave采用的是fork创建的子进程来完成的这个过程;redis内部所有涉及到RDB操作都采用bgsave方式,save命令可以放弃使用

            2.7.3 bgsave指令相关配置

            image.png

            image.png


            2.8 持久化方案三 ,RDB启动方式--自动执行

            image.png

            2.8.1 配置

            指令配置:save  second  changes

            作用:满足限定时间范围内key的变化数量达到指定数量即进行持久化

            参数:second -- 监控时间范围    changes -- 监控key的变化

            位置:在conf文件中进行配置,不要乱设置,设置不合理也是灾难性的;second和changes一般遵循前面大后面小,前面小后面大

            image.png

            范例:

            image.png

            注意:只要是在设定的时间范围内,满足条件的key数量发生变化(包括添加、修改),就会自动保存数据

            2.8.2 RDB启动方式save配置原理

            image.png

            2.9 RDB三种启动方式对比

            image.png

            image.pngimage.png

            2.10 RDB特殊启动方式

            image.png

            2.11 RDB的优点与缺点

            image.png


            2.12 AOF简介

            RDB的弊端:

            1、存储数据量较大,效率较低,基于快照的思想,每次读写都是全部数据,当数据量巨大时,侠侣非常低

            2、大数据量下的IO性能较低

            3、基于fork创建子进程,内存产生额外消耗

            4、宕机带来的数据丢失,快照思想存储是基于某个时间点的数据,无法做到即时的数据存储

            解决思路:

            1、不写全数据,仅记录部分数据

            2、改记录数据为记录操作过程

            3、对所有操作均进行记录,排除丢失数据的风险

            AOF概念:

            1、AOF(append  only  file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的,与RDB相比,可以简单的描述为:改记录数据为记录数据产生的过程

            2、AOF主要作用是解决了数据持久化的实时性,目前已经是redis持久化的主流方式,优先使用AOF方式

            

            2.13 AOF写数据过程

            image.png

            2.14 AOF写数据的三种策略

            image.png

            2.15 AOF功能开启

            配置:appendonly   yes|no,默认是no

            作用:是否开启AOF持久化功能,默认为不开启状态

            image.png

            配置AOF策略:appendfsync   always | everysec | no

            作用:AOF写数据策略

            image.png

            案例演示:

            image.png

            image.png

            image.png

            AOF其它相关配置:

            image.png

            2.16 AOF写数据遇到的问题

            image.png

            AOF重写:

            随着命令不断写入AOF,文件会越来越大,为了解决这个问题,redis引入了AOF重写机制压缩文件体积。AOF文件重写是将redis进程内的数据转化为写命令同步到新AOF文件的过程。简单说就是将对同一个数据的若干个命令执行结果转化成最终结果数据对应的指令进行记录

            AOF重写的作用:

            降低磁盘占用量,提高磁盘利用率

            提高持久化效率,降低持久化写时间,提高IO性能

            降低数据恢复用时,提高数据恢复效率

            AOF重写的规则:

            image.png

            AOF重写的方式:

            1、手动重写:bgrewriteaof 

            案例演示:

            第一步、

            image.png

            第二步、

            image.png

            第三步、重写

            image.png

            第四步、

            image.png

            

            AOF手动重写---bgrewriteaof指令工作原理

            image.png

            2、自动重写:

            auto-aof-rewrite-min-size   size

            auto-aof-rewrite-percentage   percentage  

            image.png

            注意:info指令,查看当前redis运行属性值!!!

            AOF工作流程:

            image.png

            基于everysec开启重写

            image.png

            2.17 RDB和AOF的区别

            image.png

            image.png

            2.18 持久化应用场景

            image.png

            

三、Redis事务

            3.1 事务简介

            redis事务就是一个命令执行的队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰;在开发中一般不使用redis事务,作为一个了解就好。

            一个队列,一次性、顺序性、排他性的执行一系列命令

            image.png

            3.2 事务的基本操作

            开启事务:multi 

            作用:设定事务的开始位置,此指令执行后,后续的所有指令均加入到事务中

            执行事务:exec

            作用:设定事务的结束位置,同时执行事务。与multi成对出现,成对使用

            image.png

            注意:加入事务的命令暂时进入到任务队列中,并没有立即执行,只有执行exec命令才开始执行

            3.3 事务定义过程中发现问题了怎么处理?

            取消事务:discard

            作用:终止当前事物的定义,发生在multi命令之后,exec命令之前

            image.png

            3.4 事务的工作流程

            set指令:

            image.png

            multi开启事务:

            image.png

            来一个set指令加入队列:

            image.png

            再来一个del指令加入队列:

            image.png

            来一个exec指令:执行了exec指令以后,队列消失

            image.png

            来一个discard指令:直接销毁掉队列里面的指令集

            image.png

            3.5 事务定义过程中,命令格式输入错误怎么办

            image.png

            image.png

            

            image.png

            image.png

            3.6 事务-锁

            一、业务场景一介绍

            image.png

            解决方案:

            对key添加监视,在执行exec前如果key发生了变化,终止事务执行

            watch   key1   [key2,...]

            image.png

            注意:开启watch监控要在开启事务之前,开启watch指令监控的东西如果发生改变,定义的事务将不会执行 ,返回一个nil

            image.png

            image.png

            取消对key的所有监视:

            unwatch

            image.png

            image.png


            二、业务场景二介绍

            image.png

            基于特定条件的事务执行--分布式锁:

            1、使用setnx设置一个公共锁,不存在key才能设置成功,存在则不能设置也不能替换   setnx   lock-key   value

            image.png

            利用setnx命令返回值的特征,有值则返回设置失败,无值则返回设置成功

            对于返回设置成功的,拥有控制权,进行下一步的具体业务操作;对于返回设置失败的,不具有控制权,排队或等待

            image.png

            2、操作完毕使用del释放锁

            image.png


            3.7 事务-死锁

            一、业务场景一介绍

            image.png

            解决方案:

            使用expire为锁key添加时间限定,到时不释放,放弃锁

            expire   lock-key   second

            image.png


            image.png

            image.png

            pexpire   lock-key   milliseconds

            

            由于操作通常都是微妙或毫秒级,因此该锁定时间不宜设置过大,具体时间需要业务测试后确定

            image.png

            注意这个参数选择!!!

            image.png


四、删除策略

            4.1 redis数据特征

            redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过ttl指令获取其状态

            image.png

            image.png

            image.png


            4.2 redis数据删除策略

            数据删除策略的目标:

            在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成redis性能下降,甚至引发服务器宕机或者是内存泄漏

            

            数据删除的方式:

            定时删除:

            image.png

            惰性删除:

            image.png

            定期删除:

            image.png

            image.png

            image.png

            4.3 redis逐出算法

            image.png

            image.png

            image.png

            image.png

            image.png

            4.4 服务器配置

            服务器端基础配置:

            image.png

            日志配置:

            image.png

            注意:日志级别开发期设置为verbose,生产环境中设置为notice,简化日志输出量,降低写日志IO频度

            客户端配置:

            image.png

            多服务器快捷配置:

            image.png

五、高级数据类型

            5.1 搁置

            

六、主从复制

            6.1 互联网“三高”架构

            高并发

            高性能

            高可用

            image.png

            image.png

            多台服务器连接方案:

            image.png

            image.png

            主从复制:

            image.png

            高可用集群:

            image.png

            主从复制的作用:

            image.png

            主从复制工作流程:

            image.png

            1、建立连接工作流程

            image.png

            2、实现连接

            方式一、客户端发送命令

            image.png

            master端

            image.png

            image.png

            image.png

            image.png

            image.png


            slave端

            image.png

            image.png

            image.png

            image.png

            image.png


            方式二、启动服务器参数

            image.png

            master端:

            image.png

            

            slave端:

            image.png

            image.png


            方式三、服务器配置

            image.png

            master端:

            image.png

            

            slave端:

            image.png

            image.png

            image.png

            image.png

            image.png

            3、主从断开连接

            image.png

            master端:

            image.png


            slave端:先执行下面命令

            image.png

            image.png

            4、授权访问

            image.png

七、哨兵

            7.1 待完善


八、集群

            8.1 待完善


九、企业级解决方案

            9.1 缓存预热

            宕机:服务器启动后迅速宕机

            问题排查:

            1. 请求数量较高 

            2. 主从之间数据吞吐量较大,数据同步操作频度较高

            解决方案:

            前置准备工作:

            1. 日常例行统计数据访问记录,统计访问频度较高的热点数据

            2. 利用LRU的数据删除策略,构建数据留存队列,列如:storm与kafka配合

            准备工作:

            3. 将统计结果中的数据进行分类,根据级别,redis优先加载级别较高的热点数据

            4. 利用分布式多服务器同时进行数据读取,提速数据加载过程

            实施:

            1. 使用脚本程序固定触发数据预热过程

            2. 如果条件允许,使用了CDN(内容分发网络)效果会更好

            总结:缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统,避免用户在请求的时候先请求数据库然后再缓存的问题,用户直接查询事先预热的缓存数据!

            

            9.2 缓存雪崩

            数据库服务器崩溃(1)

            1. 系统平稳运行过程中,忽然数据库连接量激增

            2. 应用服务器无法及时处理请求

            3. 对外响应408超时,或者响应500错误页面

            4. 用户得不到反馈数据,反复刷新页面

            5. 请求量越来越大,数据库崩溃

            6. 应用服务器崩溃

            7. 重启应用服务器无效

            8. redis服务器开始崩溃

            9. redis集群崩溃

            10. 重启数据库后再次被瞬间流量放倒

            问题排查:

            1. 在一个较短的时间内“缓存中较多的key集中过期”

            2. 在此周期内请求访问过期数据,redis未命中,redis向数据库获取数据

            3. 数据库同时接收到大量请求无法及时处理

            4. redis大量请求被积压,开始出现超时现象

            5. 数据库流量增大,数据库崩溃

            6. 重启后依然面对缓存中无数据可用

            7. redis服务器资源被严重占用,redis服务器崩溃

            8. redis集群呈现崩塌,集群瓦解

            9. 应用服务器无法及时得到数据响应请求,客户端用户继续刷新,来自客户端的请求数量越来越多,应用服务器崩溃

            10. 应用服务器、redis、数据库全部重启,效果依然不理想(重启只是给自己一个心理安慰罢了,redis缓存依然没有数据,必崩)

            分析问题

            1. 短时间内

            2. 大量key集中过期

            解决方案(道):

            1. 更多的页面静态化处理 (原因是页面过多的数据从缓存取)

            2. 构建多级缓存结构:Nginx缓存 + redis缓存 + ehcache缓存(纯Java的进程内缓存框架

            3. 检测mysql严重耗时业务进行优化,对数据库的瓶颈排查:列如超时查询、耗时较高事务等

            4. 灾难预警机制,监控redis服务器性能指标

                CPU占用,CPU使用率 (雪崩的典型现象CPU比较忙)

                内存容量

                查询平均响应时间

                线程数

            5. 限流、降级

            短时间内牺牲一些客户体验,限制一部分请求访问,降低应用服务器压力,待业务低速运转后再逐步放开访问

            解决方法(术):

            1. LRU与LFU切换

            2. 数据有效期策略调整

                根据业务数据有效期进行错峰,假如A类90分钟,B类80分钟,C类70分钟

                过期时间使用固定时间 + 随机值形式,稀释集中到期的key的数量,比如A类某某key90.1,A类另一key90.5等

            3. 超热数据使用永久key(区分超热普通热点)

            4. 定期维护(自动 + 人工)

                对即将过期数据做访问量分析,确认是否延时,配合访问量统计,做热点数据延时

            5. 加锁(慎用)

                拿到锁的干活,拿不到锁的就拿不到数据

            总结:

            1. 不管是道的层面还是术的层面,都要去做监控预防,道的话就是平时该怎么去设计,术的话就是出现问题要知道该去动哪些东西

            2. 缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如果能有效避免过期时间集中,可以有效解决雪崩现象的出现(约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整

            image.png

            

            9.3 缓存击穿

            数据库服务器崩溃(2)

            1. 系统平稳运行过程中

            2. 数据库连接量瞬间激增

            3. redis服务器内key无大量过期

            4. redis内存平稳,无波动

            5. redis服务器CPU正常

            6. 数据库崩溃


            问题排查:

            1. redis中某个key过期,该key访问量巨大

            2. 多个数据请求从服务器直接压到redis后,均未命中

            3. redis在短时间内发起了大量对数据库中同一数据的请求

            问题分析:

            1. 单个key高热数据

            2. key过期
            解决方案(术):

            1. 预先设定:

                以电商为例,每个商家根据店铺等级,指定若干款主打产品,在购物节期间,加大此类信息key的时长

            注意:不仅仅是购物街当天,以及后续若干天,访问峰值呈现主键降低的趋势

            2. 现场调整:

                监控访问量,对自然流量激增的数据延长过期时间,或者设置为永久性key

            3. 后台刷新数据:

                启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失

            4. 二级缓存:

                设置不同的失效时间,保障不会同时失效就行 (还是尽量分类设置过期时间,同类的商品key过期时间都加随机值浮动)

            5. 加锁:

                分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重! (不太推荐,实在没有办法的时候考虑使用)

            总结:

            缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,导致对数据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与及时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可。

            

            9.4 缓存穿透

            数据库服务器崩溃(3)

            1. 系统平稳运行过程中

            2. 应用服务器流量随时间增量较大

            3. redis服务器命中率随时间逐步降低 (redis命中率降低,对应数据库服务压力变大)

            4. redis内存平稳,内存无压力

            5. redis服务器CPU占用激增

            6. 数据库服务器压力激增

            7. 数据库崩溃


            问题排查:

            1. redis中大面积出现未命中

            2. 出现非正常的URL访问

            a、假设百度搜索redis关键字

            image.png

            b、点击关键字

            image.png

            c、得到正常的URL访问结果

            image.png

            image.png

            d、假设随意修改URL的文章id编号进行访问

            image.png

            e、得到这么个结果,redis未命中,直接进到数据库查询

            image.png

            问题分析:

            1. 获取的数据在数据库中也不存在,数据库查询未得到对应的数据

            2. redis获取到null数据未进行持久化,直接返回

            3. 下次此类数据到达,重复上述过程

            4. 出现黑客攻击   (黑客想办法在穿透redis来对数据库进行攻击,这种攻击不是为了搞数据,通过大量无效URL访问让服务器无法命中,然而给数据库带来较大的流量,导致数据库被整崩掉)

            解决方案(术):

            1. 缓存null

                对查询结果为null的数据进行缓存(长期使用,定期清理),设定短时限,例如30秒-60秒,最高5分钟,时间太久就导致内存泄露 (不是一个有效的解决方案,要是一下来几十万个数据,内存占用短时间瞬间起来)

            内存泄露:程序在申请内存后无法释放已经申请的内存空间,一次性内存泄露可以忽略,但内存泄露堆积后果很严重,memory leak(内存泄露)最终会导致 out of memory(内存不足) ,这块内存不释放,就不能再使用了,就叫这块内存泄露了。

            内存溢出:是程序在申请内存时,没有足够的内存空间供其使用。比如你需要10M的内存空间,内存空间只剩8M,这就会出现内存溢出。就是说分配的内存不足以放下数据项序列,称为内存溢出。

            2. 白名单策略

                提前预热各种分类数据id对应bitmaps,id作为bitmaps的offset,相当于设置了数据白名单。当加载正常数据时放行,加载异常数据时直接拦截(效率偏低)。

                使用布隆过滤器

            3. 实施监控

                实时监控redis命中率(业务正常范围时,通常会有一个波动值)与null数据的占比

                    非活动时段波动:通常检测3-5倍,超过5倍纳入重点排查对象

                    活动时段波动:通常检测10-50倍,超过50倍纳入重点排查对象

                根据倍数不同,启动不同的排查流程,然后使用黑名单进行防控

            4. key加密

                问题出现后,临时启动防灾业务key,对key进行业务层传输加密服务,设定校验程序,过来的key校验

                列如每天随机分配60个加密串,挑选2到3个,混淆到页面数据id中,发现key不满足访问规则,驳回数据访问

            总结:

            1. 缓存击穿访问了不存在的数据,跳过了合法数据的redis数据缓存阶段,每次访问数据库,导致对数据库服务器造成压力。通常此类数据的出现量是一个较低的值,当出现此类情况以毒攻毒,及时报警。应对策略应该在临时预案防范方面多做文章

            2. 无论是白名单还是黑名单,都是对整体系统的压力,警报解除后尽快移除


            9.5 性能指标监控

            监控指标

            image.png

            1. 性能指标

            image.png

            2. 内存指标

            image.png

            3. 基本活动指标

            image.png

            4. 基本活动指标

            image.png

            5. 基本活动指标

            image.png

            监控方式:

            image.png

            命令:

            benchmark

            image.png

            image.png

            monitor命令:打印服务器调试信息

            slowlog命令:

            image.png

            

            



【原创】 Redis入门、第一部分
03 06 2022

Reids数据库基础知识


一、Redis简介

            1.1 问题现象

            image.png

            1.2 NoSql

            NoSql:Not-Only-Sql(泛指非关系型的数据库),“作为关系型数据库的补充

            作用:应对给予海量用户和海量数据前提下的数据处理问题

            特征:不遵循SQL标准、远超于SQL性能、不支持ACID

            NoSql应用场景:对数据高并发的读写、海量数据的读写、对数据高可扩展性

            NoSql不适合的场景:需要事务支持、基于SQL的结构化查询,处理复杂的关系

            常见的NoSql数据库:Redis、memcache、HBase、MongoDB

            image.png

            image.png

            1.3 Redis

            概念:Redis(Remote Dictionary Sever)  使用C语言开发的一个开源的高性能键值对(key-value)数据库

            1.4 Redis特征

            image.png

            image.png

            redis是一个单线程+多路I/O复用机制;memcached是多线程+锁机制

            image.png

            1.5 Redis的应用

            image.png

            1.6 Redis在windows下的安装

            image.png

            1.7 命令行模式工具使用思考

            功能性命令

            清楚屏幕信息

            帮助信息查询

            退出指令

            

二、Redis基础操作

            2.1 信息添加

            功能:设置key、value数据

            命令:set  key  value

            2.2 信息查询

            功能:根据key查询对应的value,如果不存在,返回 nil 

            命令:get  key 

            2.3 清除屏幕信息

            功能:清除屏幕中的信息

            命令:clear

            2.4 帮助

            功能:获取命令帮助文档,获取组中所有命令信息名称

            命令:help  命令名称      help   @组名(help 空格 table)

            image.png

            image.png

            2.5 退出

            功能:退出客户端

            命令:quit   exit   esc(这个玩意儿慎用)


三、Redis数据类型

            3.1 数据业务使用场景介绍

            image.png

            image.png

            3.2 数据存储类型基本介绍

            Redis有5大数据存储类型,分别是string、hash、list、set、sorted_set

            redis数据存储格式:

            redis自身是一个Map,其中所有的数据都采用key:value的形式存储

            数据类型:指的是存储的数据类型,也就是value部分的类型,key部分永远都是字符串

            image.png

            3.2.1 string类型

            存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型

            存储数据的格式:一个存储空间保存一个数据

            存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用

            

            string类型数据的基本操作:

            操作成功提示integer 1   操作失败提示integer 0

            a、添加/修改数据:set   key   value

            b、获取数据:get  key 

            c、删除数据:del  key

            d、添加/修改多个数据:mset  key1  value1   key2  value2

            e、获取多个数据:mget  key1  key2

            f、获取数据字符个数(字符串长度):strlen   key

            g、追加信息到原始信息后部(如果原始信息存在就追加,否则新建):append  key  value

            image.png


            string类型数据的扩展操作:

            a、设置数值数据增加指定范围的值

            指定键的value值加1:incr  key 

            image.png

            指定键的value值加上指定整数值:incrby  key  increment

            image.png

            image.png

            指定键的value值加上指定浮点数值:incrbyfloat  key  increment

            image.png

            b、设置数值数据减少指定范围的值

            decr  key 

            image.png

            decrby  key  decrement

            image.png

            c、设置数据具有指定的生命周期

            setex  key  seconds  value  

            image.png

            psetex key milliseconds value

            image.png

            为key设置过期时间  expire key seconds

            image.png

            获取值的范围  getrange key start end

            image.png


            string作为数值操作:

            string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值类型进行计算

            string的所有操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响

            注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis数值上限范围,将报错

            

            提示:

            1、redis用于控制数据库表主键id,为数据库表主键提供生成策略,保证数据库表的主键唯一性;此方案适用所有数据库,且支持数据库集群

            2、redis控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作

            

            string类型数据操作注意事项:

            1、数据操作不成功的反馈与数据正常操作之间的差异

            image.png

            2、数据未获取到

            nil等同于null

            3、数据最大存储量

            string类型数据,单个value最大存储量512MB

            

            string类型应用场景:

            image.png

            image.png

            说明:   表名:主键字段:主键值:说明字段(粉丝、关注量等等...)

            image.png

            用json形式存放一组数据

            image.png

            注意:数据库中的热点数据key命名案例

            image.png


            3.2.2 hash类型

            新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息

            image.png

            需要的存储结构:一个存储空间保留多个键值对数据

            image.png

            

            hash类型数据的基本操作

            a、添加/修改数据:hset  key  field  value

            image.png

            b、获取数据:hget  key  field        hgetall   key

            image.png

            c、删除数据:hdel  key  field1   field2

            image.png

            d、添加/修改多个数据:hmset  key  field1  value1  field2   value2

            image.png

            e、获取多个数据:hmget  key  field1  field2

            image.png

            f、获取hash表中字段的数量:hlen  key

            image.png

            g、获取hash表中是否存在指定的字段:hexists  key  field

            image.png


            hash类型数据的扩展操作

            a、获取hash表中所有的字段名或字段值:hkeys  key     hvals  key

            image.png

            image.png

            b、设置指定字段的数值数据增加指定范围的值:hincrby key field increment(指定字段增加整数)   、  hincrbyfloat key field increment(指定字段增加浮点数)

            image.png

            image.png


            hash类型数据操作注意事项:

            1、hash类型下的value只能存储字符串,不允许存储其它类型数据,不存在嵌套现象。如果数据未获取到,对应的值为 nil

            2、每个hash可以存储2的32次方-1个键值对 

            3、hash类型十分贴近对象的数据存储形式,并且可以灵活的添加删除对象属性,但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用

            4、hgetall操作可以获取全部属性,如果内部field过多,遍历整体数据效率就会低,有可能成为数据访问瓶颈


            hash类型应用场景:

            1、电商网站购物车设计与实现(属于买家)

            image.png

            image.png

            image.png

            image.png

            当前仅仅是将数据存储到了redis中,并没有起到加速的作用,商品信息还需要二次查询数据库

            image.png

            image.png

            hsetnx  key  field  value 在此场景的使用:如果当前key中对应的field有值,就什么都不做;如果没值,我就把它加进去!!! 

            image.png


            2、双十一活动,销售手机充值卡的商家对移动、联通、电信的30元、50元100元商品推出的抢购活动,比如商品抢购上限1000单(属于卖家)

            image.png

            image.png

            image.png


            业务场景:

            string存对象(json)与hash存对象的优缺点,string讲究整体性,数据一次性整体操作,要么一次性更新要么一次性读取,以读为主;而hash因为有field字段把属性隔离开,讲究更新操作更具有灵活性,以更新为主!!!  开发的时候根据需求灵活设置数据类型


            3.2.3 list类型

            数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分

            需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序

            list类型:保存多个数据,底层使用双向链表存储结构实现,哪边都能进  哪边都能出

            image.png

            image.png


            list类型数据的基本操作

            a、添加/修改数据:lpush key value [value ...]       rpush key value [value ...] 

            image.png

            b、获取数据/查询数据:

            lrange key start stop 获取列表指定范围的元素,lrange key start stop ,这里的start代表开始,stop代表结束,当stop为-1的时候表示取到最后一个值,当stop为-2的时候,表示取到倒数第二个值,以此类推;lrange key 0 -1,表示全部取出

            左边进去的1  2  3 ,左边查询出来3  2  1 

            image.png

            右边进去的 1  2  3,左边查询出来 1  2  3 

            image.png


            c、lindex key index ,通过索引从列表中获取/查询元素

            image.png

            d、llen key ,获取链表的长度

            image.png

            e、从左边“移除”数据(移出、弹出),lpop  key,当队列中数据移出完以后会删掉key

            image.png

            f、从右边“移除”数据(移出、弹出), rpop  key,当队列中数据移出完以后会删掉key

            image.png


            list类型数据的扩展操作

            规定时间内获取并移除数据

            a、 blpop key [key ...] timeout     删除并获取列表的第一个元素,或阻止直到有可用的元素

            image.png

            拿不出来就一直在那儿等,直到设置时间到,返回nil

            image.png

            image.png

            b、 brpop key [key ...] timeout     删除并获取列表的第一个元素,或阻止直到有可用的元素

            image.png

            

            list类型数据操作注意事项:

            1、list中保存的数据都是string类型的,数据总量是有限的,最多2的32次方-1个元素(4294967295)

            2、list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作

            3、获取全部数据操作结束的索引设置为-1

            4、list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载


            list类型应用场景:

            1、微信朋友圈点赞,要求按照点赞顺序现实点赞好友信息

            image.png

            从列表中删除元素,移除指定数据,lrem key count value 

            image.png

            image.png

            2、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示,粉丝列表需要将最近关注的粉丝列在前面

            image.png

            image.png

            image.png

            image.png


            3.2.4 set类型

            数据存储需求:存储大量的数据,在查询方面提供更高的效率

            需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询

            set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的

            image.png

            image.png


            set类型数据的基本操作

            a、添加数据:sadd key member [member ...]

            image.png

            b、获取全部数据:smembers key

            image.png

            c、删除数据:srem key member [member ...]

            image.png

            d、获取集合数据总量:scard key

            image.png

            e、判断集合中是否包含指定数据:sismember key member

            image.png


            set类型应用场景:

            1、应用场景举例1

            image.png

            set类型数据的扩展操作:

            a、随机获取集合中指定数量的数据:srandmember key [count]

            image.png

            b、随机获取集合中的某个数据并将该数据移出集合:spop  key

            image.png

            提示:redis应用于随机推荐类信息检索,列如热点歌单推荐,热点新闻推荐,热卖旅游路线推荐,应用APP推荐,大V推荐等


            2、应用场景举例2

            image.png


            image.png

            c、求两个集合的交集:sinter key [key ...]

            image.png

            d、求两个集合的并集:sunion key [key ...]

          image.png  

            e、求两个集合的差集:sdiff key [key ...]

            image.png

            f、求两个集合的交集、并集、差集并存储到指定的集合中

            image.png

            image.png

            g、将指定数据从原始集合中移动到目标集合中:smove source destination member

            image.png

            提示:

            image.png

            set类型数据注意事项:

            1、set类型不允许数据重复,如果添加的数据在set中已经存在,将只保留一份

            image.png

            2、set虽然与hash存储结构相同,但是无法启用hash中存储至的空间

            image.png

            

            3、应用场景举例3

            image.png

            image.png

            image.png

            校验工作:redis提供基础数据还是提供校验结果?    尽量提供基础数据,不在redis数据端做数据校验


            4、应用场景举例4

            image.png

            image.png

            提示:redis应用于同类型数据的快速去重            


            5、应用场景举例5

            image.png

          image.png

            

            3.2.5 sotred_set类型

            数据存储需求:数据排序有利于数据的有效显示,需要提供一种可以根据自身特征进行排序的方式

            需要的存储结构:新的存储模型,可以保存可排序的数据

            sorted_set类型:在set的存储结构基础上添加可排序字段

            image.png

            

            sorted_set数据的基本操作:

            a、添加数据:zadd key [NX|XX] [CH] [INCR] score member [score memb

            image.png

            b、获取全部数据(从小到大):zrange key start stop [WITHSCORES]

            image.png

            image.png

            加了参数withscores以后的结果:

            image.png

            c、获取全部数据(从大到小):zrevrange key start stop [WITHSCORES]

            image.png

            d、删除数据:zrem key member [member ...]

            image.png

            e、按条件获取数据(从小到大):zrangebyscore key min max [WITHSCORES] [LIMIT offset count]

            image.png

            f、按条件获取数据(从大到小):zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]

            image.png

            附加limit条件查询:

            image.png

            g、按条件索引删除数据:zremrangebyrank key start stop

            image.png

            h按条件删除数据:zremrangebyscore key min max

            image.png

            image.png

            i、获取集合数据总量:zcard score

            image.png

            j、统计集合某个范围的数据:zcount  key  min  max

            image.png

            k、集合交集操作:zinterstore destination numkeys key [key ...] [WEIGHTS weight] [AG

            image.png


            sorted_set类型应用场景:

            1、应用场景举例1

            image.png

            m、获取数据对应的索引(由小到大):zrank  key  member

            image.png

            n、获取数据对应的索引(由大到小):zrank  key  member

           image.png

            o、score值得获取

            image.png

            p、score值修改

            image.png

            提示:

            image.png


            sorted_set类型数据注意事项:

            1、score保存的数据存储空间是64位,如果整数范围是-9007199254740992~9007199254740992

            2、score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时候要慎重

            3、sorted_set底层存储还是基于set结构,因此数据不能重复,如果重复添加相同的数据,score将被反复覆盖,保留最后一次修改结果



            image.png

            image.png

            


【原创】 PHP8
27 05 2022

PHP8的使用

            1、 PHP基本介绍

            1.1、什么是PHP

            image.png

            1.2、PHP是怎么执行的

            image.png

            2、PHP8介绍

            PHP8是PHP语言的一个主版本更新,它包含了很多新功能与优化,包括命名参数、联合类型、注解、构造器属性提升、match表达式、nullsafe运算符、JIT、并改进了类型系统、错误处理、语法一致性。

            2.1、JIT(即时编译)编译器

            JIT(Just-In-Time)即时编译器,是PHP8.0中最重要的新功能之一,可以极大地提高性能。

            JIT编译器将作为扩展集成到php中Opcache扩展,用于运行时讲某些操作码直接转换为cpu指令。仅在启用Opcache的情况下,JIT才有效。

            2.2、Opcache扩展

            Opache将通过PHP脚本预编译的字节码存储到共享内存中来提升PHP的性能,存储预编译字节码的好处就是:省去了每次加载和解析PHP脚本的开销。

            Opcache开启:

            zend_extension=opcache

            Opcache配置:

            image.png

            JIT配置:在php.ini中,加到上面opcache配置后面

           opcache.jit=tracing

           opcache.jit_buffer_size=100M



            

            



【原创】 内存分析
18 05 2022

计算机内存分析介绍

        1、计算机内存组成

            1.1、计算机内存结构介绍

            在计算机中,内存又称主存储器,是CPU能够直接寻址的存储空间,由半导体器件制成,主要由存储体、控制线路、地址寄存器、数据寄存器、和地址译码电路五部分组成。

            在计算机组成结构中有一个很重要的部分是存储器,它是用来存储程序和数据的部件。对计算机来说,有了存储器才有记忆功能,才能保证正常工作。存储器的种类很多,按其用途可分为主存储器和辅助存储器,主存储器又称为内存储器,内存又称为主存,是CPU能够直接寻址的存储空间,与辅助存储器相比,有容量小、读写速度快、价格高等特点。

            1.2、技术指标

            存储容量:在一个存储器中可以容纳存储单元总数的大小、字节数。

            存取时间:启动到完成一次存储操作所经历的时间,主存速度单位ns。

            存储周期:连续启动两次操作所需间隔的最小时间,主存速度单位ns。

            存储器带宽:单位时间内存储器所存取的信息量,它是衡量数据传输速率的重要指标单位是b/s(位/秒),或者是B/S(字节/秒)。

            存放一个机器字的存储单元,通常称为字存储单元,相应的单元地址叫字地址。而存放一个字节的单元,称为字节存储单元,相应的地址称为字节地址。如果计算机中可编址的最小单位是字存储单元,则该计算机称为按字编址的计算机。如果计算机中可编址的最小单位是字节,则该计算机称为按字节编址的计算机。一个机器字可以包含数个字节,所以一个存储单元也可以包含数个能够单独编址的字节地址。例如,PDP-11系列计算机,一个16位二进制的字存储单元可存放两个字节,可以按字地址寻址,也可以按字节地址寻址。当用字节地址寻址时,16位的存储单元占两个字节地址。

        2、内存数据存放

            2.1、大端和小端存储

            小端:就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

            大端:就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

            image.png

            2.2、由什么决定存储方式

            需要说明的是,计算机采用大端存储还是小端存储是由CPU来决定的,我们常用的X86体系CPU采用的是小端存储,ARM也是采用的小端存储,但有些CPU却采用的大端,比如:Sun、PowerPC

        3、数据在内存中的形式

            数据在内存中是以二进制形式存放的,数值是以补码表示的;字符、汉字、特殊符号等都有对应的码值(ASCII/unicode码的码值),对应字符的码值转换成二进制数存放在内存中




【原创】 Mysql数据库入门、第二部分
16 05 2022

Mysql数据库基础知识


九、MYSQL约束

            9.1 约束基本介绍

            约束用于确保数据库数据满足特定的商业规则,在mysql中,约束包括not null(非空)、unique(唯一)、primary key(主键)、foreign key(外键)、check(检查)五种

            9.1.1、主键使用方式:字段名 类型 primary key

            primary key主键基本作用:用于唯一的表示表行的数据,当定义主键约束后,该列不能重复

            应用实例一:演示主键的使用

            第一步:创建表

            image.png

            第二步:添加数据

            image.png

            primary key主键使用细节讨论:

            1、primary key不能重复且值不能为空

            2、一张表最多只能有一个主键,但可以是复合主键,多个字段合起来是一个主键

            应用实例一:复合主键使用

            错误:

            image.png

            创建复合主键

            image.png

            image.png

            image.png

            3、主键的指定方式有两种

            一是直接在字段名后面指定:字段名 primary key

            二是在表定义的最后写primary key(列名,列名...)

            image.png

            4、可以使用desc 表名  查看primary key的情况

            image.png

            5、在实际的开发中,每个表往往都会设计一个主键


            9.1.2、not null(非空)使用方式:字段名  类型 not null 

            开发中,如果在列上定义了not null,那么在插入数据时,必须为列提供数据           


            9.1.3、unique(唯一)使用方式:字段名  字段类型  unique

            定义了唯一约束后,该列值是不能重复的

            应用实例一:演示unique的使用

            image.png

            image.png

            unique 使用细节讨论:

            1、如果没有指定主键的情况下也没有指定not null,则unique字段可以有多个null值

            image.png

            2、如果一个列(字段)  有unique not null 约束,使用效果类似primary key 

            3、一张表中可以有多个unique 字段


            9.1.4、foreign key(外键)使用方式:foreign key (本表(从表、外键表)的字段名)references  主表名(主键名或unique字段名) 

            外键基本介绍:

            外键用于定义主表和从表之间的关系,外键约束要定义在“从表”上,主表则必须具有“主键约束” 或是“unique“约束,当定义外键约束后,“要求外键列数据必须在主表的主键列存在或是为null“

            image.png

            应用实例一:演示外键使用

            第一步:创建主表,字段有班级编号、班级名称

            image.png

            第二步:创建从表,字段有学生编号、学生名字、学生所在班级编号(外键)

            image.png

            第三步:添加测试数据

            image.png

            从表设置了外键,主表中没有id为300的数据,所以从表的这条添加的语句不会成功,insert into my_stu values(3,'螳螂',300)[添加失败],但是外键字段的值如果允许为空 (没有设置not null 非空约束),则可以添加成功

            image.png

            image.png

            外键使用细节讨论:

            1、外键指向的表的字段,要求是primary key 或者是unique

            image.png

            2、表的类型必须是innodb,这样的表才支持外键;mysql从5.5版本以后,默认引擎innodb;查看mysql版本使用命令status

            image.png

            image.png

            3、外键字段的类型要和主键字段的类型一致(长度可以不一样)

            image.png

            4、外键字段的值,必须在主键字段中出现过,或者为null [前提是外键字段允许为null]

            image.png

            5、一旦建立外键关系,数据就不能随意删除了;如果要删除,除非把设置外键的从表中的对应ID的数据都删除,才能去删除主表中的该条ID记录值

            image.png

            image.png


            9.1.5、check    使用方式:列名   类型   check  (check条件)

            基本介绍:check用于强制行数据必须满足的条件,假定在之前的员工表的sal列上定义了check约束,并要求sal列值在1000~2000之间,如果不在1000~2000之间就会提示出错; oracle 和 sql server均支持check,但是mysql5.7目前还不支持check,只做语法校验,但不会生效

            应用实例一:演示check使用

            第一步:创建表

            image.png

            第二步:添加数据 ,  一样是能添加到数据表中,所以,只做语法校验,但不会生效

            image.png


            9.2 自增长

            在某张表中,存在一个id列(整数),我们希望在添加记录的时候从1开始,自动增长。 使用方式:字段名 整型 primary key auto_increment

            image.png

            应用实例一:演示自增长的使用

            第一步:创建表

            image.png

            image.png

            第二步:添加数据

            image.png

            image.png

            自增长使用细节讨论:

            1、一般来说自增长是和peimary key配合使用的

            2、自增长也可以单独使用 [需要配合一个unique]

            3、自增长修饰的字段为整数类型的(虽然小数类型也可以,但是非常非常少这样用的)

            4、自增长默认从1开始,也可以通过命令修改,  alter table 表名 auto_increment = 10(具体整形值)  

            image.png

            5、自如果你添加数据时,给自增长字段(列)指定有值,则以指定的值为准;以下图为例,以后再添加数据的时候,id就从667开始了

            image.png

            

十、MYSQL索引

            10.1 索引基本介绍

            说起提高数据库性能,索引是最物美价廉的方案了,不用加内存,不用改程序不用调SQL,查询速度就有可能提高百倍千倍;

            

            说索引之前先说一下mysql安装在硬盘文件目录下面data文件夹中的文件

            1、表存储引擎是myisam,在data目录下面会看到3类文件:frm、myi、myd

            *.frm-表定义,是描述表结构的文件

            *.MYD-"D"数据信息文件,是表的数据文件

            *.MYI-"I"索引信息文件,是表数据文件中的任何索引的数据树

            2、表存储引擎是InnoDB,在data目录下面会看到2类文件:frm、ibd

            *.frm-表定义,是描述表结构的文件

            *.ibd-表数据和索引文件,该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据

            3、另外db.opt文件

            用来记录该库的默认字符集编码和字符集排序规则使用的。也就是说你创建数据库指定默认字符集和排序规则,那么后续创建的表如果没有指定字符集和排序规则,那么该新建的表将采用db.opt文件中指定的属性。

            

            10.2 索引原理:

            "没有使用索引"   的时候查询过程如下图:

            全表扫描,从id最小查询到id最大,即使查询条件是id=1,它也会全表扫描,查询速度非常慢

            image.png

            image.png


            二叉树简介:

            1、二叉树的叶子节点就是没有子节点的节点,一棵树中没有子节点(即度为0),的节点称为叶子节点,简称“叶子”,又称为终端节点。

            2、二叉树特点是每个节点最多只能有两颗子树,且有左右之分。

            3、二叉树是n个有限元素的集合,该集合或者为空,或者由一个称为根的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树,当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称为一个节点。

            建立索引的二叉树(数据结构),在1-9中间找一个位于最大编号id和最小编号id的中间的数,假设是5,比5小的摆放位置在左边,比5大的摆放位置在右边,然后继续在1和5之间中间数,假设为2,然后比2小的继续摆放在2左边,比2大的摆放在2的右边,所有数据按照此方式分析下去

            image.png

            使用了索引的时候查询过程如下图:

            第一步:where条件id为1,假设1--9二分,中间找到5,然后5右边的数据就不再查找了,如下图所示

            image.png

            第二步:where条件id为1,1比5小,再往左边再二分,假设1--5中间找到2,然后2右边的数据也不再查找,假设是一个800万的数据中查找,大概是23次左右就能找到,比顺序扫描快了不知道多少多少,如下图所示

            image.png

            二叉树五种基本形态:

            图a:空二叉树

            图b:只有一个根节点的二叉树

            图c:只有左子树

            图d:只有右子树

            图e:完全二叉树

            image.png


            B树简介:

            概念:

            叶子节点:B树的叶子节点就是没有子节点的节点,一棵树中没有子节点(即度为0),的节点称为 "叶子节点",简称“叶子”,又称为 "终端节点",叶子节点的指针为空。

            非叶子节点:B树的 "非叶子节点" 就是 "非终端节点",即“树枝”。

            基本定义:

            1、根节点至少有两个子节点

            2、叶子节点都在同一高度

            3、如果非叶子节点有n个关键字,那么它有n+1个子节点,切这n个节点递增排列

            

            image.png

            image.png


            B+树简介:

            B+树是由B树演变而来的,所以它具有B树的所有特性,另外还具有如下两点

            1、B+树的非叶子节点只有关键字,不存放数据

            2、B+树的叶子节点之间用指针相连,是一个双向链表

            image.png

            案例一:

            第一、

            image.png

            第二、

            image.png

            image.png

            第三、

            image.png

            image.png

            第四、

            image.png

            总结:

            image.png


            不得不提的时间单位换算:

            1s = 1000ms(10的3次方毫秒)= 1000000us(10的6次方微秒)= 1000000000ns(10的9次方纳秒) = 10的12次方皮秒(ps)

            假设3Ghz的CPU主频,再由CPU分配资源,诸多进程等待,获取CPU调度来处理MYSQL进程,假设分得的资源的一次处理周为10us,800万数据23次查询,耗时230us/0.23ms,再经过网络传输或者计算偏差等,建立索引后查询800万数据的耗时预估也就在几百微妙到几十毫秒之间


            不加索引速度为什么那么慢:全表扫描查询

            加索引为什么速度会很快:形成一个索引的数据结构,比如二叉树/B树/B+树

            加索引代价:

            1、创建索引后,文件变大,磁盘变大

            2、对dml(update、delete、insert)语句的效率影响,删除/修改/添加一个数据,可能导致存索引的二叉树/B+树的结构发生变化,需要重对索引进行维护,对速度有影响   在我们实际的项目中,大多数项目select的时候比update、delete、insert多得多; 假设一个UP主有一千万粉丝,一天发10篇文章,“理论情况下不使用其他扩展插件”,全都浏览了文章, insert才10次,而select就是1亿 次


            10.3、创建索引

            创建索引后,只对创建了索引的列(字段)有效

            image.png

            image.png

            10.3.1、添加索引的两种方式

            image.png

            image.png

            

            10.3.2、删除索引  drop  index  索引名 on   表名

            image.png

            image.png

            删除主键索引

            image.png

            10.3.3、修改索引,  操作是先删除再添加


            10.3.4、查询索引

            1、show index from t25

            image.png

            2、show indexes from t25  

            image.png    

            3、show keys from t25     

            image.png         

            4、desc 表名

            image.png  

            image.png

            Non_unique:值为0代表唯一索引,值为1代表非唯一索引


            image.png

            

            10.3.5、索引的类型

            1、主键索引:主键自动的为主索引(为字段添加的primary key)

            image.png

            2、唯一索引:唯一索引(unique)

            image.png

            3、普通索引:普通索引(index)

            image.png

            4、全文索引:全文索引(fulltext),适用于MyISAM表引擎。   假如我们要在一篇文章中搜索一个人的名字,希望搜索得很快,就可以在文章的字段上建一个全文索引,在实际的开发中,一般不使用mysql自带的全文索引,而考虑使用的全文索引框架 Solr和Elasticsearch

            

            10.3.6、索引总结

            哪些列上适合创建索引呢

            1、较频繁作为查询条件字段应该创建索引

            image.png

            2、唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件,下面的性别字段不适合创建索引

            image.png 

            3、更新非常频繁的字段不适合创建索引,因为会频繁的去更新索引结构

            image.png

            4、不会出现在where字句中字段不该创建索引  

            mysql索引失效的情况有哪哪些???

            ① 使用了左模糊查询,“%xxx”,或者是"%x%"的查询

            因为B+树是根据索引值进行排列的,前缀不确定的时候可能是,“小张”,"二张"之类的所有的情况,就只能通过全表扫描的方式来查询

            ② 对索引使用了函数的情况

            因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,所以使用函数的时候就不会走索引了

            ③ where子句中的or

            因为 OR 的含义就是两个只要满足一个即可,因此只有一个条件列进行了索引是没有意义的,只要有条件列没有进行索引,就会进行全表扫描,因此索引的条件列也会失效

            ④ 对索引字段使用了表达式

            select * from sys_user where user_id+10 =50;

            在 where 中条件使用了条件表达式的时候,数据表中的索引就失效了,实际是因为 Mysql 需要将索引字段取出来之后再进行表达式的条件判断,因而进行了全表扫描,导致索引失效


            如何避免mysql索引失效???

            ① 全部采取值匹配,对查询语句中的列都指定索引

            ② 如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过索引中的列。

            ③ 避免在索引上进行运算,索引将失效

            ④ 避免字符串查询不加单引号,索引失效

            ⑤ 避免select * 的写法

            ⑥ 避免以“%”开头的模糊查询,“%”开头的模糊查询将失效,尽量采用尾部模糊查询

            ⑦ in会走索引,not in 索引将失效

            ⑧ 在合适的业务场景使用or查询



十一、MYSQL事务

            11.1 事务基本介绍

            事务用于保证数据的一致性,它由相关的dml语句组成,该组dml语句要么全部成功,要么全部失败。如转账就需要用事务来处理,用以保证数据的一致性。

            image.pngimage.pngimage.png

            11.2 事务和锁

            当执行事务操作时(dml语句),mysql会在表上加锁,防止其他用户改表的数据,这对用户来说时非常重要的。

            11.3 mysql数据库控制台事务的几个重要操作

            1、start  transaction           --开始一个事务

            2、savepoint  保存点名       --设置保存点

            3、rollback to 保存点名       --回退事务

            4、rollback                          --回退全部事务

            5、commit                          --提交事物,所有的操作生效,不能退回

            

            回退事务:在介绍事务前,先介绍一下保存点(savepoint),保存点时事务中的点,用于取消部分事务,当结束事务时,会自动删除该事务定义的所有保存点;当执行回退事务时,通过指定保存点可以回到指定的点

            提交事务:使用commit语句可以提交事务,当执行了commit语句后,会确认事务的变化、结束事务、删除保存点、释放锁、数据生效。当使用commit语句结束事务后,其他会话将看到事务变化后的新数据。


            image.png


            案例演示一、

            开启事务:

            image.png

            设置保存点:

            image.png

            执行dml操作:

            image.png

            再设置一个保存点:

            image.png

            回退到保存点i:

            image.png

            回退到保存点a: 中间的其他保存点会删除!!!

            直接回退到事务开始的状态:

            image.png

            提交事务,所有的操作生效,不能再回退,保存点删除,commit以后没有后悔药...


            11.4 mysql事务细节讨论

            1、如果不开启事务,默认情况下,dml操作时自动提交的,不能回滚

            2、如果开启一个事务,你没有创建保存点,你可以执行rollback,默认就是回到事务开始的状态

            3、在事务还没有提交的时候,你可以在事务中创建多个保存点 ,比如:savepoint aaa  ;执行dml语句;  savepoint bbb;

            4、可以在事务还没提交前,选择回到哪个保存点

            5、使用mysql事物机制需要innodb存储引擎才可以使用,myisam不行。

            6、开始一个事物可以使用start transation,也可以使用set autocommit = off。

            

            11.5 mysql事务隔离级别

            概念:mysql隔离级别,定义了事务与事务之间的隔离程度。 

            image.png

            基本介绍:

            1、多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的准确性。

            2、如果不考虑隔离性,可能会引发如下问题:

            脏读:一个事务读取另一个事务尚未提交的改变时(update、insert、delete),产生脏读

            不可重复读:同一查询在同一事务中多次进行,由于其他提交事务所做的“修改”或“删除”,每次返回不同的结果集,此时发生不可重复读

            image.png

            幻读:同一查询在同一事务中多次进行,由于其他提交事务所做的“插入”操作,每次返回不同的结果集,此时发生幻读

            

            应用实例一、演示mysql事务隔离级别,read uncommitted(读未提交)     结果出现脏读、不可重复读、幻读

            第一步、查询当前默认隔离级别:select @@tx_isolation,  默认可重复读

            image.png

            第二步、把其中一个控制台的隔离级别设置为read  uncommitted(读未提交)

            语法:set session transaction isolation level  read  uncommitted

            image.png

            image.png

            第三步、脏读

            控制台1

            image.png

            控制台2

            image.png

            第四步、不可重复读

            控制台1修改了id=1的数据余额为800

            image.png

            控制台2读取到了另一事务提交的改变(修改、删除); 事务1的提交影响了事务2对表读的操作

            image.png

            第五步、幻读

            控制台1提交了新添加的数据

            image.png

            控制台2读取到了另一事务提交的改变(插入) ;事务1的提交影响了事务2对表读的操作

            image.png


            应用实例二、演示mysql事务隔离级别,read committed(读已提交)     结果出现不可重复读、幻读,不会出现脏读

            第一步、控制台1开启事务

            image.png

            第二步、控制台2修改事务隔离级别为read  committed(读已提交),并且开启事务

            语法:set session transaction isolation level  read  committed

            image.png

            image.png

            第三步、脏读

            控制台1添加了数据,并读取数据如下

            image.png

            控制台2读取数据,并没有读取到刚才控制台1事务添加的数据

            image.png

            第四步、不可重复读

            控制台1修改了数据,并且提交

            image.png

            控制台2读取数据,又读取到了控制台1事务做的修改,出现不可重复读

            image.png

            第五步、幻读

            控制台1添加了id为5的数据,并提交

            image.png

            控制台2查询到了控制台1事务的提交

            image.png


            应用实例三、演示mysql事务隔离级别,repeatable read(可重复读)  不会出现脏读、不可重复读、幻读

            第一步、控制台1开启事务

            image.png

            第二步、控制台2修改事务隔离级别为repeatable read(可重复读),并且开启事务

            语法:set session transaction isolation level  repeatable read

            image.png

            第三步、脏读、不可重复读、幻读   

            控制台1添加、修改了数据,并提交数据

            image.png

            image.png

            image.png

            控制台2读取数据,依然没有变化

            image.png


            应用实例四、演示mysql事务隔离级别,Serializable(可串行化)不会出现脏读、不可重复读、幻读

            第一步、控制台1开启事务

            image.png

            第二步、控制台2修改事务隔离级别为Serializable可串行化),并且开启事务

            语法:set session transaction isolation level  Serializable

            image.png

            第三步、控制台1添加一个语句,修改一个语句

            image.png

            控制台1并没有提交事务,控制台2查询,卡在那里等待,超时

            image.png

            image.png

            控制台1事务提交

            image.png

            控制台2查询

            image.png

            

            11.6 mysql设置隔离

            1、查看当前会话隔离级别  select @@tx_isolation

            image.png

            2、查看系统当前隔离级别   select @@global.tx_isolation

            image.png

            3、设置当前会话隔离级别   set session transaction isolation level  (隔离级别)

            image.png

            4、设置系统当前隔离级别   set session transaction isolation level  (隔离级别)

            image.png

            5、mysql默认的事务隔离级别是repeatable read,一般情况下没有特殊要求,没有必要修改(因为该隔离级别满足绝大部分项目需求)

            6、全局修改,设置mysql隔离级别,修改my.ini配置文件

            image.png

            

            11.7 mysql事务ACID

            1、原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

            2、一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态

            3、隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据干扰,多个并发事务之间要相互隔离

            4、持久性:持久性指一个事务一旦被提交,它对数据库中的数据改变是永久性的,接下来即使数据库发生故障也不应该对其有任何影响


            11.8 mysql表类型和存储引擎

            基本介绍:

            1、mysql的表类型由存储引擎决定,主要包括myisam、innodb、memory等...

            2、mysql数据表主要支持6种类型,分别是:CVS、Memory、ARCHIVE、MRG MYISAM、MYISAM、InnoDB

            3、这6种又分为两类,一类是“事务安全型”,比如:InnoDB;其余都属于第二类,称为“事务非安全型”

            

            查看所有的存储引擎:show engines

            image.png

            主要的存储引擎及其特点

            image.png

            image.png

            几种常用表类型的区别:

            innodb存储引擎:支持事务、支持外键、支持行级锁、写入速度慢一些

            myisam存储引擎:不支持事务和外键、写入速度快、支持表级锁

            memory存储引擎:数据存储在内存中、执行速度很快(没有磁盘IO读写)、默认支持索引(哈希表)、重启mysql服务或者操作系统以后,数据消失,但是表结构还在

            image.png

            image.png

            修改表存储引擎:alter table 表明 engine= innodb/myisam


            11.9 mysql视图

            image.png

            视图基本概念:

            1、视图是一个虚拟表,其内容由查询定义,同真实的表一样,视图包含列,其数据来自对应的真实表(基表)

            2、视图和基表关系示意图

            image.png

            image.png

            对视图的总结:

            image.png

            视图的基本使用:

            1、创建视图:create view 视图名 as select语句

            image.png

            image.png

            2、查看视图结构:desc 视图名

            image.png

            3、查询视图数据:select 字段  from  视图名

            image.png

            3、alter view 视图名 as select语句    修改一个视图,其实相当于重新定义一个视图了

            image.png

            image.png

            4、查看创建视图的指令: show create view 视图名

            image.png

            5、drop view 视图1   视图2

            image.png

            image.png

            

            视图细节讨论:

            1、创建视图后,到数据库去看,对应视图只有一个视图结构文件

            2、视图的数据变化会影响基表,基表的数据变化也会影响到视图(insert、update、delete)


            视图的最佳实践:

            image.png

            image.png


十二、MYSQL管理

            12.1 mysql用户管理

            当我们在项目开发时,可以根据不同的开发人员,赋给他相应的mysql操作权限!!!

            mysql中的用户都存在系统数据库的mysql中的user表

            image.png

            其中user表重要字段说明:

            1、host字段:允许登录的“位置”,localhost表示该用户只允许本机登录,也可以指定IP登录

            2、user字段:用户名

            3、authentication_string字段:密码,是通过mysql的password()函数加密之后的密码


            创建用户

            create  user  '用户名' @ '允许登录的位置'  identified  by '密码'      创建用户的同时指定密码

            image.png

            image.png

            密码是password()函数加密的

            image.png

            删除用户

            drop user '用户名'  @ ‘允许登录的位置’

            image.png

            其他用户登录

            image.png

            image.png

            image.png

            

            image.png

            普通用户登录修改自己的密码:set password = password('112235')

            image.png

            image.png

            普通用户修改其他用户的密码:set password  for '用户'  @  '允许登录位置' = password('密码')

            这里,访问mysql数据库权限不够,被拒绝

            image.png 

            使用root用户来修改其他用户密码

            image.png


            12.2 mysql权限管理

            权限列表

            image.png

            1、使用root账户给其他账户赋权限

            如果被赋值权限的用户存在,可选里面设置了密码则表示修改密码,如果不存在就是创建用户并赋权限

            image.png

            2、回收用户授权

            revoke  权限列表  on  库.对象名  from  '用户名'@'登录位置';

            3、权限刷新指令

            FLUSH  PRIVILEGES;


            应用实例一、用户管理练习

            image.png

            第一步、使用root用户创建用户

            image.png

            第二步、使用root用户创建testdb库和news表

            image.png

            第三步、使用root用户给普通用户分配权限

            image.png

            第四步、测试用户权限

            image.png

            第五步、使用root用户修改密码为abc

            image.png

            第六步、重新登录

            image.png

            第七步、回收权限

            image.png

            已经没有了删除权限,删除失败

            image.png


            mysql管理细节说明:

            1、在创建用户的时候,如果不指定Host,则为%,%表示所有IP都有链接权限

            image.png

            image.png

            2、也可以指定IP创建:  create   user   '用户名'@'IP' 

            image.png

            image.png

            3、在删除用户的时候,如果host不是%,需要明确指定  '用户'@'host值'

            image.png

            host不是%的情况

            image.png

            image.png

            image.png


【原创】 第二十一章、ORM
21 04 2022

    第二十一章、GORM

        一、ORM介绍

            1.1 Gin框架简介

            中文官方文档:https://gorm.io/zh_CN/

            GORM是Golang目前比较热门的数据库ORM操作库,对开发者也比较友好,使用非常方便简单,使用上主要就是把struct类型和数据库表记录进行映射,操作数据库的时候不需要直接手写Sql代码,这里主要介绍MySQL数据库。

                image.png

            1.2 安装

            go get gorm.io/gorm                 安装最新版本  go get -u gorm.io/gorm

            go get  gorm.io/driver/sqlite      安装最新版本  go get -u gorm.io/driver/sqlite


            1.3 ORM优缺点

            优点:提高开发效率

            缺点:牺牲执行性能、牺牲灵活性、弱化了开发者的SQL能力


        二、CURD操作

            2.1 链接数据库

            image.png


            image.png


            image.png


            2.2 创建记录

            image.png

            image.png

            用指定的字段创建记录

            image.png

            创建一个记录且忽略传递的字段值,创建结构体中 Omit()没有指定的字段值

            image.png

            批量插入数据,将一个slice传给Create方法,GORM会生成一条单独的SQL语句插入所有数据,并填写回主键的值,钩子方法也会被调用

            image.png

            分批插入数据

            image.png

            image.png


            2.3 默认值

            image.png

            案例演示:

            image.png

            image.png


            2.4 查询

            image.png

            image.png

            


            1.5 约定

            GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间

            遵循 GORM 已有的约定,可以减少您的配置和代码量。如果约定不符合您的需求,GORM 允许您自定义配置它们


            



【原创】 第二十章、gin框架
19 04 2022

第二十章、Gin框架

        一、Gin框架介绍

            1.1 Gin框架简介

            Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API,性能要好得多,多亏了 httprouter,速度提高了 40 倍。 如果您需要性能和良好的生产力,您一定会喜欢 Gin。

        二、快速入门

            2.1 下载并安装gin

            go get -u github.com/gin-gonic/gin

            2.2 gin渲染HTML

            image.png

            image.png


            终端curl 命令发送请求

            image.png

            2.3 自定义模板函数

            image.png

            image.png

            image.png

            2.4 静态文件处理

            image.png

            image.png

            image.png

            2.5 使用模板继承

            image.png

            image.png


            

            以下模板继承来自于网络其他方式:

            header文件:

            image.png


            footer文件:

            image.png

    

            extends文件:

            image.png

            

            代码如下:

            image.png



        三、gin框架返回数据

            3.1 获取URL参数

            3.1.1 通用处理方式Handle()方式

            image.png


            3.1.2 分类处理engine.GET()        engine.POST(),POST表单默认解析方式x-www-form-urlencoded或from-data格式的参数

            image.png

            image.png

            image.png


            3.2 多数据格式返回请求结果

            image.png


            3.3 表单实体绑定

            image.png

            image.png

            image.png

            image.png


            image.png

            3.4 Any路由的使用

            image.png

            3.5 文件上传

            3.5.1 单文件上传

            image.png

            3.5.2 多文件上传

            image.png

            image.png

            3.6 为不存在的路由配置处理函数

            image.png

            image.png

            image.png

            3.7 日志记录进文件

            image.png

            image.png

            


        四、重定向

           image.png

             4.1 HTTP重定向

            image.png

             4.2 路由重定向

            image.png


        五、路由分组

            4.1 路由分组

            image.png

            image.png

                  image.png


            image.png

            4.2 简化路由分组

            image.png


        五、中间件

            5.1 中间件

            image.png

            image.png

            

            案例演示一,所有API共用中间件:

            image.png

            案例演示二,单独一个API使用中间件方式:

            image.png

            image.png


            5.2 context.Next函数,将中间件代码一分为二执行,执行完成相关调用以后回来继续context.Next()后面的处理函数

            image.png

            案例演示:

            image.png

            image.png

            

            image.png


            5.3 context.Abort函数,阻止调用处理函数

            image.png

            image.png

            页面没有反馈,空白

            image.png

            5.5 context.Abort函数和context.Next函数应用

            image.png


            5.6 路由组注册中间件

            image.png

            5.7 中间件注意事项

            image.png






【原创】 第十九章、go模板渲染
13 04 2022

第十九章、Go模板渲染

        一、Go原生模板渲染

            1.1 Go原生模板解析、模板渲染

            image.png

            image.png

            image.png

            1.2 模板语法

            image.png

            image.png

            image.png

            多个变量渲染

            image.png

            image.png


            1.3 模板中的注释

            image.png

            image.png


            1.4 pipeling

            image.png

            1.5 变量

            image.png

            image.png

            1.6 移除空格

            image.png

            image.png

            1.7 条件判断

            image.png

            image.png

            image.png

            image.png

            1.8 range遍历

            image.png

            image.png

            image.png

            image.png

            1.9 with

            image.png

            image.png

            image.png

            1.20 比较函数

            image.png

            1.21 预定义函数

            image.png

            image.png

            image.png

            案例演示:

            image.png

            image.png

            image.png

            

            1.22 原生模板嵌套

            image.png

            image.png

            image.png

            image.png

            

            1.23 block使用

            image.png

            image.png

            案例演示:

            image.png

            image.png

            image.png

            image.png

            1.24 修改默认标识符

            image.png

            image.png

            image.png

            1.25 转义js代码,防止xss攻击

            image.png

            image.png

            

        


            

            

            

            

             

            

            

            

            





            

            


【原创】 第十八章、数据操作
09 04 2022

第十八章、数据操作

        一、golang操作mysql

            1.1 安装第三方库

            进入到项目的src目录下,在终端执行:go get github.com/go-sql-driver/mysql

            image.png

            image.png

            1.2 连接mysql    sql.Open()

            image.png

            image.png

            image.png

            1.3 往mysql写入数据DB.Exec()

            image.png

            1.4 查询数据

            单行查询:db.QueryRow()

            image.png

            image.png

            多行查询:db.Query()

            image.png

            1.5 更新数据DB.Exec()

            image.png

            1.6 删除数据DB.Exec()

            image.png

            image.png


            1.7 mysql预处理 func (db *DB) Prepare(query string) (*stmt,error)

            一、预处理查询

            image.png

            二、预处理添加、删除、编辑语句类似

            image.png

            1.8 mysql事务DB.Begin()    DB.Commit()    DB.Rollback()

            image.png

            image.png

            image.png

            image.png

            

            1.9 演示sql注入     注意:任何时候,都不应该在项目中拼接SQL语句!!!

            image.png

            image.png

            image.png

            image.png


        二、golang操作sqlx库

            2.1 sqlx库基本介绍

            sqlx是 Go 的软件包,它在出色的内置database/sql软件包的基础上提供了一组扩展。

            该库兼容sql原生包,同时又提供了更为强大的、优雅的查询、插入函数。

            该库提供四个处理类型,分别是:

            sqlx.DB – 类似原生的 sql.DB;sqlx.Tx – 类似原生的 sql.Tx;sqlx.Stmt – 类似原生的 sql.Stmt, 准备 SQL 语句操作;sqlx.NamedStmt – 对特定参数命名并绑定生成 SQL 语句操作。

            提供两个游标类型,分别是:

            sqlx.Rows – 类似原生的 sql.Rows, 从 Queryx 返回;sqlx.Row – 类似原生的 sql.Row, 从 QueryRowx 返回。

            2.2 安装第三方库

            进入到项目的src目录下,在终端执

            image.png

            image.png

            2.3 链接数据库   sqlx.Connect()

            image.png

            image.png

            image.png

            2.4 单行查询Db.Get()

            image.png

            image.png

            2.5 多行查询Db.Get()

            image.png

            image.png

            2.6 Db.NameEcex()方法用来绑定SQL语句与结构体或map中的同名字段

            image.png

            image.png

            2.7 注意事项

            image.png

            

            

            

            

            



            


            

            


            

            


【原创】 Redis 基本使用
30 03 2022

Redis的基本使用

        1、Redis基本介绍

            1.1、redis 基本介绍

            image.png

            1.2、redis安装和基本使用

            image.png

            1.3、redis的优势

            异常快速:Redis速度非常快,每秒能执行约11万集合,约81000条每秒。

            支持丰富的数据类型:Redis原生支持最大多数开发人员已经知道的,像列表,集合,分类,散列等数据类型。这使得它非常容易解决各种各样的问题,因为我们知道哪些数据类型问题是可以通过它的处理得更好。

            操作原子性:所有Redis的操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。

            MultiUtility工具:Redis是一个多实用的工具,可以在一些像缓存,消息,队列用例中使用(Redis原生支持发布/订阅),在应用程序,如Web应用程序的会话,网络页面点击数短期数据等等。

            


            操作原理图:

            image.png

            链接redis:

            image.png

            

            1.3、redis操作指令一览

            网址:http://redisdoc.com/

        2、Redis基本使用

            2.1、redis的基本使用

            image.png

            2.3、Redis的CURD

            2.3.1、Redis的五大数据类型

            String(字符串)、Hash(哈希)、Lish(链表)、集合(Set)、有序集合(Zset)


            String基本介绍:

            a、String是redis最基本的类型,一个key对应一个value

            b、String类型是二进制安全的,除普通字符串外,也可以存放图片等数据;单个value最大值512M

            image.png

            c、set操作,set[如果key存在就相当于修改,如果不存在相当于添加];set key value;

            d、get操作,直接 get key键

            e、del操作,直接del key键

            image.png

            f、set设置过期时间, setex  key  过期时间 value

            image.png

            g、mset同时设置一个或多个 key-value对,如果给定的key已经存在,那么mset会用新值覆盖原来的旧值,格式:mset key1 value1 key2 value2,可以使用mget 获取全部值   也可以单独使用get 指定的键

            image.png


            Hash基本介绍(hash类似golang里面的map):

            a、Redis hash是一个键值对集合,每个hash可存储多达2的32次方-1个字段-值对(超过42亿)

            b、Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象

            c、设置指令格式: hset key field value    

            d、获取指令格式: hget key field 

            image.png

            e、获取所有: hgetall key

            image.png

            f、一次性设置所有:hmset key field value field value ...

            image.png

            g、一次性获取所有:hmget key field field ...

            image.png

            h、删除指定字段:hdel key field

            image.png

            i、hlen统计一个hash有几个元素

            image.png

            j、查看hash表key中,是否存在给定的field字段,指令格式:hexists key field

            image.png


            List(列表)基本介绍:

            列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

            List本质是个链表,List的元素是有序的,元素的值可以重复。

            List数据结构分析:

            image.png

            a、设置一个链表,从左边插入:lpush key value value value ...    依次放入aaa  bbb  ccc

            image.png

            b、获取链表内容,从左边“取出”(只是取出,链表中还存在这个数据):lrange key start stop ,这里的start代表开始,stop代表结束,当stop为-1的时候表示取到最后一个值,lrange key 0 -1,表示全部取出;依次取出 ccc  bbb  aaa  

            image.png

            image.png

            image.png

            c、设置一个链表,从右边插入:rpush key value value value ...    依次放入ddd  eee

            image.png

            此刻再从左边取出, 看看数据结构:

            image.png

            d、从链表左边“弹出”(从链表中弹出移走数据):lpop key

            image.png

            e、从链表右边“弹出”(从链表中弹出移走数据):rpop key

            image.png

            f、删除整个链表:del key

            image.png

            注意事项:

            a、lindex  :按照索引下标获得元素(从左到右,编号从0开始)

            b、LLEN key :返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0

            c、List数据,可以从左 或者从右插入添加

            d、如果值全移除,对应的键也就消失了


            Set(集合)基本介绍:

            Redis的Set是string类型的无序集合,底层是Hash Table数据结构,Set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复

            a、添加数据到集合中:sadd key member member member ...   (member:成员)

            image.png

            b、从集合中取出所有数据:smembers key

            image.png

            c、判断值是否是成员:sismember  key  member 

            image.png

            d、删除集合中指定的成员:srem key member

            image.png


            注意事项:

            a、元素的值不能重复

            image.png


【原创】 Mysql数据库入门、第一部分
27 03 2022

Mysql数据库基础知识

一、Mysql5.7.19解压版安装

            Mysql基本介绍:

            Mysql是一个关系型数据库管理系统,由瑞典MYSQL AB公司开发,属于Oracle旗下产品。

            Mysql是一个单进程多线程的数据库,在innodb中大概3种线程为:1、主线程Master Thread;2、IO Thread线程,用于异步处理写请求;3、purge Thread线程,用于删除undo日志。


    网址:https://dev.mysql.com/

    下载地址https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-winx64.zip

            特别说明:

            image.png

            image.png

            安装步骤:

            1.下载得到zip文件

            2.解压的路径不要带有中文和空格

            3.解压到这里

            image.png

            4.添加环境变量,其目的是:可以在dos下的任意目录操作mysql相关指令

            WIN + E -> 右键此电脑 -> 属性 -> 高级系统设置 -> 高级选项卡 -> 环境变量, 在path环境变量中增加mysql安装目录,到那个bin目录下面,如:D:\mysql-5.7.19-winx64\bin\

            image.png

            5.在D:\mysql-5.7.19-winx64\目录下创建my.ini文件,需要我们自己创建

            [client]

            port=3306

            default-character-set=utf8

            

            [mysqld]

            #设置为自己的mysql安装目录

            basedir=D:\mysql-5.7.19-winx64\

            #设置为mysql的数据目录

            datadir=D:\mysql-5.7.19-winx64\data\

            port=3306

            character_set_server=utf8

            #跳过安全检查,注释以后需要输入正确的用户名和密码才能登录

            #skip-grant-tables

            6.使用管理员身份打开cmd,并切换到D:\mysql-5.7.19-winx64\bin目录下执行 mysqld -install (mysqld后面有个空格)

            image.png

            7.初始化数据库  mysqld --initialize-insecure --user=mysql    ,如果执行成功,生成data目录

            image.png

            8.启动mysql服务net start mysql;停止mysql服务net stop mysql;

            image.png

            image.png

            9.进入mysql终端mysql -u root -p [安装完成以后,root账户,密码为空]

            10.修改root用户密码

            use mysql;

            update user set authentication_string=password('你要设置的密码') where user='root' and Host='localhost';

            或者下面修改密码语句也可以:

            set password for root@localhost=password('你的密码');

            flush  privileges;   //刷新权限

            

二、数据库

            1、连接到mysql服务的命令:mysql -h localhost -P 3306 -u root -p123123123   

            注意:-P端口这个P是大写;-p密码这里没有空格

            image.png

            2、mysql三层结构

            image.png

            image.png

            3、sql语句分类

            image.png

            4、创建数据库数据表操作

            4.1、创建数据库

            create database 数据库名;

            4.2、创建数据库,同时设置字符集

            create database 数据库名 character set utf8;

            image.png

            4.3、显示数据库语句

            show databases;

            image.png

            4.4、显示数据库创建语句,下图中的反引号 `` 是用来规避关键字的

            show create databases db_name;

            image.png

            4.5、数据库删除语句

            drop database if exists ab_name; (谨慎使用,生产环境一定不要轻易操作,仔细确认再的确要删除才执行)

            image.png

            4.6、备份数据库,在dos命令行操作

            mysqldump -u 用户名 -p 密码 -B 数据库1  数据库2  数据库n > 文件位置:\文件名.sql

            image.png 

            4.7、恢复数据库,需要登录进mysql再执行操作

            source 文件夹:\beifen.sql

            image.png

            4.8、备份数据库的表,

            mysqldump -u 用户名 -p 密码 数据库 表1  表2  表n > 文件位置:\文件名.sql

            image.png


三、表

            1、创建mysql数据表,语法如图所示:

            image.png

            image.png


四、Mysql常用数据类型(列类型/字段类型)

            1、mysql列类型-即mysql数据类型(数据类型选择遵守保小不保大)

            image.png

            1.1、数值类型

            image.png

            image.png

            1.2、文本类型(字符串类型)

            image.png

            1.3、二进制数据类型

            image.png

            1.4、时间日期类型

            image.png

            image.png


五、列类型

            5.1、mysql列类型之bit

            image.png

            image.png

            image.png

            image.png

            image.png

            5.2、mysql列类型之数值型

            5.2.1小数类型

            image.png

            image.png

                        

            image.png

            

            5.3、mysql列类型之字符串类型

            5.3.1char(这里是字符数,char(10),即使只存5个汉字,但是也占用10个字符空间 )、varchar(这里面是字符数,varchar(10)可以存储10个中文汉字,utf8编码占用内存空间31-33个字节)(utf8编码varchar最大21844个字符,gbk编码varchar最大32766个字符

            image.png

            image.png

            

            字符串使用细节1:占用多大字节空间根据表的编码决定(utf8中文3个字节,英文一个字节;gbk中文2个字节)

            image.png

            image.png

            字符串使用细节2:

            image.png

            字符串使用细节3:

            image.png

            为什么char比varchar快呢?

            char类型在存放数据的时候,中间是没有间隔的,数据本身是有空格的,但是数据段之间是没有间隔的,这是因为我们在创建列的时候已经告诉MySQL列的长度了,MySQL在查询数据的时候,只需要按部就班寻找就行了,不需要在中途计算这个数据段的长度。

但是varchar类型的存放就不同了,它是动态分配存储空间的,在每个数据段开头,都要有一段空间来(1~2个字节)存放数据段的长度信息,在数据段的结尾也还有一段空间(1个字节)标记此字段的节数。MySQL在读取一个数据段的时候,首先要读开头,比如读到了3,说明数据段的长度是3,之后就不多不少,只读3个字节,也只分配3个字节的存储空间。所以MySQL在遍历数据的时候,磁针要比char类型的列,多读很多次磁盘来获取字段的真实长度,这就是为什么varchar比char查询效率低的原因了。

            image.png

            字符串使用细节4:

            image.png

            image.png


            5.4、mysql列类型之日期类型

            image.png

            image.png


六、表操作

            6.1、修改表基本介绍

            image.png

            添加字段:

            image.png

            查看表结构:

            image.png

            修改表结构(字段类型):

            image.png

            image.png

            注意:int(10),这个10表示数据显示的长度为10;  int(2)并不表示数据大小的最大值为99,其大小和int表示的最大值一样,只是表示查询时显示的结果长度为2位; 而char(10)  varchar(10), 这里的10表示不管什么字符集,最多只能存10个字符!!!

            删除表结构(字段):

            image.png

            修改表名:

            image.png

            修改表字符集:

            image.png

            查看建表语句:

            image.png

            image.png

            修改字段名称:

            image.png


七、CURD  C[create] U[update] R[retrieve 检索、找、取] D[delete]

            7.1、添加语句

            image.png

            image.png

            image.png

            注意细节:

            image.png


            7.2、更新语句 

            image.png

            image.png

            image.png

            image.png

            注意细节:

            image.png


            7.3、删除语句 (注意:删除的时候一定要带条件,不然会导致整个表的数据全部被删除 !!!)

            image.png

            image.png

            注意了:

            image.png

            image.png


            7.4、select查询语句  (SQL中的重点、难点)

            image.png


            7.4.1 指定字段查询

            image.png


            7.4.2 指定字段去重查询

            image.png

            image.png


            7.4.3 使用表达式对查询的列进行运算

            image.png

            image.png

            image.png            

            

            7.4.4 在select语句中使用as语句

            image.png

            image.png

            7.4.5 在where字句中经常使用的运算符

            image.png

            >  <   like  and 

            image.png

            image.png

            查询姓氏姓金的

            image.png

            image.png

            (between  and )   是一个闭区间 

            image.png

            or

            image.png

            in

            image.png

            order by    order by语句应该位于select语句的结尾

            image.png

            image.png

            image.png

            image.png


            7.5、合计/统计函数

            7.5.1、count函数

            image.png

            image.png

            count(字段) 返回非空的字段满足条件的数量!!!

            image.png

            image.png

            image.png

            image.png

            7.5.2、sum函数

            image.png

            image.png

            image.png

            统计一个班级语文成绩的平均分

            image.png

            注意:sum函数仅对数值起作用,对其他类型值求sum没有意义;  还有多列求和的时候“,”不能少!!!

            7.5.3、avg函数

            image.png

            image.png

            7.5.4、max/min函数

            image.png

            image.png


            7.6、分组统计

            image.png

            按照部门分组来查询

            image.png

            显示每个部门的每种岗位的平均工资和最低工资

            image.png


            image.png

            显示平均工资低于2000的部门编号和它的平均工资

            image.png

            下面这个使用1次avg函数的查询方式效率高一点

            image.png

            

            7.7、字符串函数

            image.png

            7.7.1 返回字串字符集

            image.png

            7.7.2 连接字串,把多个列拼接成一列(把字串粘在一起)

            image.png

            7.7.3 INSTR(string,substring)  返回substring在string中出现的位置,从1开始,没有则返回0

            image.png

            7.7.4 转成大写小写  UCASE/LCASE

            image.png

            image.png

            7.7.5 LEFT(string,length) / RIGHT(string,length)   从string的左边 / 右边起,取length个字符

            image.png

            image.png

            7.7.6 LENGTH(string)   返回string的长度(字节长度)

            image.png

            image.png

            7.7.7 REPLACE(str,search_str,replace_str) 在str中用 replace_str 替换 search_str   

            image.png

            7.7.8 STRCMP(string1,string2) 逐字符比较两字串的大小, 函数用于比较两个字符串,如果两个字符串都相同,则返回0,如果根据定义的顺序第一个参数小于第二个参数,则返回-1,而当第二个参数小于第一个参数时,则返回1。

            image.png

            7.7.9 substring(str,position,[length]) 从str的position位置开始 [从1开始计算] ,取出length个字符;如果第三个参数不给,就默认取出到末尾

            image.png

            7.7.10 ltrim(string)    rtrim(string)    trim(string)   去掉string的左边、右边、两端空格

            image.png

            以首字母小写的方式显示所有员工emp表的姓名

            image.png

            image.png

            

            7.8、数学函数

            image.png

            7.8.1 abs()函数

            image.png

            7.8.2 bin()函数, 十进制转二进制

            image.png

            7.8.3 ceiling(num)函数,向上取整,得到比num大的最小整数

            image.png

            7.8.4 conv(num,from_base,to_base)函数, 进制转换函数

            image.png

            7.8.5 floor(num)函数,向下取整,得到比num小的最大整数

            image.png

            7.8.6 format(num,decimal_places)函数,对num 保留 decimal_places位小数(四舍五入)

            image.png

            7.8.7 hex(num)函数,转成十六进制

            image.png

            7.8.8 least(num1,num2, [...])函数,求最小值

            image.png

            7.8.9 mod(numerator,denominator)函数,求余

            image.png

            7.8.10 rand([seed] rand [seed])函数,返回随机数,其范围为0 <= v <= 1.0

            image.png

            注意:使用rand(),每次返回不同的随机数,范围0 <= v <= 1.0;使用rand(seed)返回随机数,范围0 <= v <= 1.0,如果seed不变,该随机数也不会变化


            7.9、时间日期相关函数

            image.png

            7.9.1 current_date()函数,返回当前日期; 查询的时候current_date 可以带小括号也可以不带

            image.png

            7.9.2 current_time()函数,返回当前时间

            image.png

            7.9.3 current_timestamp()函数,返回当前时间戳

            image.png

            image.png

            7.9.4 now()函数,返回当前日期时间

            image.png

            image.png

            应用实例1:显示所有新闻信息,发布日期只显示日期,不显示时间

            image.png

            7.9.5 date_add(date,interval  d_value   d_type)函数在date上加上时间或者日期

            应用实例2:查询在10分钟内、一天内、一个月内、一年内添加的数据      

            image.png

            image.png

            7.9.6 date_sub(date,interval  d_value   d_type)函数, 在date上减去时间或者日期

            image.png

            image.png

            7.9.7 datediff(date1,date2)函数,返回两个日期差(结果是天)

            image.png


            image.png

            7.9.8 year|month|date(datetime)     年月日

            image.png

            7.9.9 unix_timestamp()函数, 返回自1970-01-01 00:00:00  到当前时间的秒数

            image.png

            7.9.9 FROM_UNIXTIME()函数,   把一个unix_timestamp秒数[时间戳]  转成指定格式的日期

            image.png

            

            7.10、加密和系统函数

            image.png

            7.10.1  user()函数,查询当前是哪个用户

            image.png

            7.10.2  database()函数,查询当前使用的数据库名

            image.png

            7.10.3  md5()函数,为字符串算出一个md5  32位的字符串,常用于用户密码加密

            image.png

            7.10.4  password()函数,加密函数,mysql数据库的用户密码就是用password函数加密的

            image.png

            image.png

            image.png


            7.11、流程控制函数

            image.png

            image.png

            7.11.1 if(expr1,expr2,expr3)函数,如果 expr1为true则返回expr2,否则返回expr3

            image.png

            7.11.2 ifnull(expr1,expr2)函数,如果expr1不为空,则返回expr1,否则返回expr2

            image.png

             7.11.3 判断是否为null,要使用is null, 判断不为空,使用is not null

            image.png

            7.11.4  SELECT CASE  WHEN expr1  THEN  expr2  WHEN expr3   THEN  expr4  ELSE  expr5  END ;  【多重分支】 如果expr1为 true 则返回expr2,如果expr3为 true 则返回expr4, 否则返回expr5

            image.png


八、MYSQL查询加强

            8.1 mysql多表查询

            image.png

            8.2  在mysql中,日期类型可以直接比较

            image.png

            8.3  like模糊查询,   %:表示0到多个任意字符    _:表示单个任意字符

             显示首字母为N的员工的工资和姓名  

            image.png     

             显示第三个字符为小写n的员工工资和姓名

            image.png    

             显示没有上级的职员信息 就是判断mgr字段为null,  判断null   使用 is null

            image.png    

             根据工资升序倒序查询

            image.png

            image.png

             根据工资倒序排序,部门升序排序

            image.png



            image.png

            image.png

            8.4  limit分页查询

            image.png

            image.png


            8.5  使用分组函数和分组子句 group by

            应用实例一:显示每种岗位的雇员总数、平均工资

            image.png

            应用实例二:显示雇员总数,以及获得奖金的雇员数

            count(字段),如果字段的值为null,则count()不会统计

            image.png

            image.png

            应用实例三:显示雇员总数,以及没有获得奖金的雇员数

            image.png

            image.png

            应用实例四:显示管理者的总人数

            image.png

            应用实例五:显示最大薪资差

            image.png

            应用实例六:统计各个部门的平均工资,并且大于1000,按照平均工资从高到低排序,取出前两行记录

            image.png

            

            注意::语句顺序!!!

            image.png


            8.6  多表联合查询

            应用实例一:多表查询,显示雇员名字、雇员工资、及所在部门的名字

            image.png

            image.png

            当多表查询不加条件的时候:

            image.png

            image.png

            分析:从第一张表中取出一行和第二张表进行组合,返回结果,结果包含两张表的所有列,上面两表查询不加条件的时候,结果就有32行,这样的多表查询默认处理返回的结果,称为笛卡尔集

            image.png

            image.png

            应用实例二:多表查询,显示雇员名字、雇员工资、部门编号、及所在部门的名字

            注意:当我们需要指定某个表的列时,需要使用  表名.列名的方式

            image.png

            小技巧:多表查询的条件不能少于表的张数-1,如:3表查询,条件至少要两个,才不会出现笛卡尔集

            应用实例三:多表查询,显示雇员名字、雇员工资、部门编号为10的部门、及所在部门的名字

            image.png


            8.7  多表联合查询-自连接

            什么是自连接:自连接指在同一张表的链接查询(将同一张表看做两张表)

            自连接的特点:1、把同一张表当做两张表来说使用    2、需要给表取别名   表名  表别名   3、列名不明确,可以指定列的别名   列名  as  列的别名

            image.png

            image.png

            image.png


            过程分析:同一张表某条记录的mgr = 同一张表某条记录的empno

            image.png

            image.png

            第一步:

            image.png

            第二步:

            image.png

            第三步:

            image.png

            

            8.8  子查询

            什么是子查询:嵌入在sql语句中的select语句,也叫嵌套查询

            单行子查询:指只返回一行数据的子查询语句

            多行子查询:指只返回多行数据的子查询语句,使用关键字 IN

            应用实例一:显示与smith同一部门的员工

            第一步:查询部门编号

            image.png

            第二步:把上面的select语句当做子查询来使用

            image.png

            应用实例二:查询和部门10的工作相同的雇员的名字、岗位、工资、部门号,但是不包含10号部门自己的雇员

            第一步:查询10号部门的工作岗位有哪些

            image.png

            像以下情况需要过滤

            image.png

            第二步:把上面查询的结果当做子查询

            image.png


            8.9  子查询当做临时表

            image.png

            image.png

            image.png

            

            image.png

            image.png

            image.png

            

            image.png

            image.png

            image.png


            8.10  在多行子查询中使用all操作符和any操作符

            应用实例一:显示工资比部门30的所有员工的工资高的员工姓名、工资和部门号

            image.png

            image.png

            应用实例二:显示工资比部门30的其中一个员工的工资高的员工姓名、工资和部门号

            image.png

            8.11  多列子查询

            多列子查询是指查询返回多个列数据的子查询语句

            应用实例一:查询与smith的部门和岗位完全相同的所有雇员(不包含smith本人)

            第一步:得到smith的部门和岗位

            image.png

            第二步:把上面的查询当做子查询来使用,并且使用多列子查询的语法进行匹配

            image.png

            image.png

            应用实例二:

            image.png

            第一步:先得到每个部门的平均工资和部门号

            image.png

            第二步:把上面的结果当做子查询,和emp进行多表查询

            image.png

            应用实例三:查询每个部门工资最高的人

            image.png

            应用实例四:查询每个部门的信息(包括:部门号、编号、地址)和人员数量

            第一步:部门号、编号、地址在dept表

            

            第二步:各个部门人员数量 -> 构建一个临时表

            image.png

            第三步:组合查询

            image.png

            image.png

            

            8.12  自我复制数据(蠕虫复制)

            有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此方法为表创建海量数据

            应用实例一:把emp表得记录复制到my_tab1中

            第一步:从其他表复制

            image.png

            第一步:自我复制

            image.png

            image.png

            image.png

            多次点击,数据成倍增长

            image.png


            应用实例二:删除掉一张表中重复记录

            第一步:先创建一张表  下面语句,把表emp的结构(列),复制到my_tab2中

            image.png

            第二步:添加数据

            image.png

            查询,已经有重复数据

            image.png

            第三步:去除重复数据

            image.png

            1、创建一张临时表

            image.png

            2、把数据去重以后添加到临时表

            image.png

            3、清除掉my_tab2的数据记录

            image.png

            4、把my_tmp表的记录复制到my_tab2

            image.png

            5、drop掉临时表my_tmp

            image.png


            8.13  合并查询

            有些在实际的应用中,为了合并多个select语句的结果,可以使用集合操作符union(联合)、union all(联合所有)

            应用实例一:union all  该操作用于取得两个结果集的并集,当使用该操作时,不会取消重复行

            image.png

            image.png

            image.png

            应用实例二:union 该操作与union all类似,但是会自动去掉结果集中重复行

            image.png


            8.14  mysql表外连接

            image.png

            左外连接:如果左侧的表完全显示(即使左侧的表和右侧的表没有匹配的记录),我们就说是左外连接;  语法:select field1,field2,... from 表1 left join 表2  on  条件[表1就是左表,表2就是右表]

            右外连接:如果右侧的表完全显示(即使右侧的表和左侧的表没有匹配的记录),我们就说是右外连;  语法:select field1,field2,... from 表1 right join 表2  on  条件[表1还是叫左表,表2还是叫右表]

            

            应用实例一:列出部门名称和这些部门员工名字和工作,同时要求显示那些没有员工的部门

            第一步:这里只有三个部门

            image.png

            但实际上是有四个部门的

            image.png

            SQL:

            


            应用实例二:使用左外链接,显示所有人的成绩,如果没有成绩,也要显示该同学的姓名和id,成绩显示为空

            第一步:传统的外键

            image.png

            image.png

            image.png

            第二步:改成左外连接

            image.png

            应用实例三:使用右外链接,查询所有成绩,如果没有名字匹配,显示为空

            image.png

            应用实例四:查询部门的名称和这些部门员工信息(名字和工作),同时列出那些没有员工的部门

            image.png

            image.png

            总结:在开发中,绝大多数情况下还是使用前面学过的多表查询

            

                    


【原创】 第十七章、网络编程
22 03 2022

第十七章、网络编程

        一、网络编程基本介绍

            golang的主要设计目标之一就是面向大规模后端服务程序,网络通信是服务端程序必不可少的。

            1.1、网络编程两种方式:

            a、TCP socket编程,是网络编程的主流,之所以叫TCP socket编程,是因为底层基于TCP/IP协议的,比如:QQ

            b、B/S结构的HTTP编程,我们使用浏览器去访问服务器时,使用的就是http协议,而http底层依旧是用TCP socket实现的,比如:京东商城

        二、TCP/IP协议

            TCP/IP(Transmission Control Protocol/Internet Protocol)的简写,中文名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是Internet最基本的协议,Internet国际互联网络的基础,简单的说,就是由网络层的IP协议和传输层的TCP协议组成

            2.1、OSI与TCP/IP参考模型

            image.png

            2.2、网线、网卡、无线网卡

            image.png

            2.3、聊天工具案例

            image.png

            2.4、IP地址

            image.png

            2.5、端口介绍

            image.png

            image.png

            image.png

            image.png

             使用Telnet链接IP和端口:

             第一步、win10搜索控制面板

             第二步、点击启用或关闭windows功能

             image.png

             第三步、安装Telnet

             image.png

             第四步、使用telnet IP 端口号   ; ctrl + ] 退出,quit退出...

             image.png


            2.6、TCP Socket编程的客户端和服务器端

            image.png


            2.7、TCP Socket编程入门案例

            要求:

            image.png

            分析:

            image.png

            服务端:

            image.png

            服务端代码:

            image.png

            image.png

            客户端代码:

            image.png

            改进:

            image.png


        三、Redis基本介绍

            3.1、需求分析

            image.png

            3.2、技术储备-redis 

            3.2.1、redis 基本介绍

            image.png

            3.2.2、redis安装和基本使用

            image.png

            操作原理图:

            image.png

            链接redis:

            image.png

            

            3.2.3、redis操作指令一览

            网址:http://redisdoc.com/

            3.2.4、redis的基本使用

            image.png

            3.3、Redis的CURD

            3.3.1、Redis的五大数据类型

            String(字符串)、Hash(哈希)、Lish(链表)、集合(Set)、有序集合(Zset)


            String基本介绍:

            a、String是redis最基本的类型,一个key对应一个value

            b、String类型是二进制安全的,除普通字符串外,也可以存放图片等数据;单个value最大值512M

            image.png

            c、set操作,set[如果key存在就相当于修改,如果不存在相当于添加];set key value;

            d、get操作,直接 get key键

            e、del操作,直接del key键

            image.png

            f、set设置过期时间, setex  key  过期时间 value

            image.png

            g、mset同时设置一个或多个 key-value对,如果给定的key已经存在,那么mset会用新值覆盖原来的旧值,格式:mset key1 value1 key2 value2,可以使用mget 获取全部值   也可以单独使用get 指定的键

            image.png


            Hash基本介绍(hash类似golang里面的map):

            a、Redis hash是一个键值对集合

            b、Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象

            c、设置指令格式: hset key field value    

            d、获取指令格式: hget key field 

            image.png

            e、获取所有: hgetall key

            image.png

            f、一次性设置所有:hmset key field value field value ...

            image.png

            g、一次性获取所有:hmget key field field ...

            image.png

            h、删除指定字段:hdel key field

            image.png

            i、hlen统计一个hash有几个元素

            image.png

            j、查看hash表key中,是否存在给定的field字段,指令格式:hexists key field

            image.png


            List(列表)基本介绍:

            列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

            List本质十个链表,List的元素是有序的,元素的值可以重复。

            List数据结构分析:

            image.png

            a、设置一个链表,从左边插入:lpush key value value value ...    依次放入aaa  bbb  ccc

            image.png

            b、获取链表内容,从左边“取出”(只是取出,链表中还存在这个数据):lrange key start stop ,这里的start代表开始,stop代表结束,当stop为-1的时候表示取到最后一个值,lrange key 0 -1,表示全部取出;依次取出 ccc  bbb  aaa  

            image.png

            image.png

            c、设置一个链表,从右边插入:rpush key value value value ...    依次放入ddd  eee

            image.png

            此刻再从左边取出, 看看数据结构:

            image.png

            d、从链表左边“弹出”(从链表中弹出移走数据):lpop key

            image.png

            e、从链表右边“弹出”(从链表中弹出移走数据):rpop key

            image.png

            f、删除整个链表:del key

            image.png

            注意事项:

            a、lindex  :按照索引下标获得元素(从左到右,编号从0开始)

            b、LLEN key :返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0

            c、List数据,可以从左 或者从右插入添加

            d、如果值全移除,对应的键也就消失了


            Set(集合)基本介绍:

            Redis的Set是string类型的无序集合,底层是Hash Table数据结构,Set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复

            a、添加数据到集合中:sadd key member member member ...   (member:成员)

            image.png

            b、从集合中取出所有数据:smembers key

            image.png

            c、判断值是否是成员:sismember  key  member 

            image.png

            d、删除集合中指定的成员:srem key member

            image.png

            注意事项:

            a、元素的值不能重复

            image.png


            3.3、Golang操作Redis

            3.3.1、安装第三方开源redis库

            image.png

            golang下载第三方扩展库:

            https://github.com/gomodule/redigo

            安装:进入到gopath目录下,在终端执行:go get github.com/gomodule/redigo/redis

            image.png

            3.3.2、String类型数据操作

            image.png

            3.3.3、Hash类型数据操作

            image.png


            image.png

            image.png


            3.3.4、Redis连接池基本介绍

            a、事先初始化一定数量的链接,放入到连接池

            b、当Go需要操作Redis的时候,直接从Redis连接池取出链接即可

            c、可以节省零时获取Redis链接的时间,从而提高效率

            d、示意图

            image.png

            核心代码:

            image.png

            连接池使用案例:

            image.png

            image.png

            

        四、用户即时通讯系统

            4.1、需求分析

            image.png

            4.2、功能一,显示客户端菜单

            image.png

            4.3、功能二,完成用户登录

            image.png

            

          image.png

            4.4、功能三,完成客户端可以发送消息本身,服务端可以正常接收到消息,并根据客户端发送的消息判断用户的合法性,并返回相应的LoginResMes

            image.png

            编译:去到项目的根目录执行,go build -o xxx.exe  从src下的目录开始直到文件所在的包

            image.png

            服务端代码改进以后的框架结构图:

            image.png

            客户端代码改进以后的框架结构图:

            image.png

            4.5、功能四,在redis手动添加测试用户,并画图+说明

            image.png

            image.png

            输入的用户名在redis中存在则登录,否则退出系统并给出相应的提示(账号密码错误或者用户不存在)

            




            

            



            



            

            



            

            



            

            







            

            


【原创】 第十六章、反射
18 03 2022

第十六章、反射

        一、基本介绍

            1.1、反射的基本介绍

            image.png

            image.png

            反射使用到的包

            image.png            


            1.2、反射的概念

            image.png

            image.png

            示意图:

            image.png

            image.png


            1.3、先看一个问题,反射的应用场景

            场景一

            image.png

            场景二

            image.png

            1.4、反射快速入门案例

            image.png

            image.png

            image.png

            image.png

            1.4、反射使用注意事项和细节

            image.png

            image.png

            image.png

            注意事项1:获取变量的类别,返回的是一个常量

            image.png

            image.png

            1.5、反射遍历结构体字段,调用结构体方法

            最佳实践1:

              image.png

            案例演示:

            image.png

            image.png

            image.png

            image.png

            最佳实践2

            image.png

            代码:

            image.png

            image.png  

            image.png          




【原创】 第十五章、goroutine和channel
12 03 2022

第十五章、goroutine和channel

        一、基本介绍

            1.1、什么是并行?

            在同一“时刻”,多件事情一起做;多线程程序在多核上运行,就是并行。特点:多个任务作用在多核CPU上,从微观的角度看,在同一时间点上,有多个任务在同时执行

            1.2、什么是并发?

            多线程程序在单核上运行,就是并发。特点:多个任务作用在一个CPU上;从微观的角度看,在一个时间点上只有一个任务在执行

            1.3、什么是线程?

            线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流。

            1.4、什么是进程?

            进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,一个进程中可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行,一个程序至少有一个进程,一个进程至少有一个线程。

            可以这么理解进程和线程,启动迅雷软件是一个进程,然后下载很多个电影资源就是多个线程;(程序加载到内存,运行起来就是进程)

            image.png


            1.5、什么是go协程?

            Go主线程(有程序员直接称之为线程/也可以理解成进程),一个Go线程上可以起多个协程,Go 协程可以看作是轻量级线程。与线程相比,创建一个 Go 协程的成本很小。因此在 Go 应用中,常常会看到有数以千计的 Go 协程并发地运行。

            “没有哪个程序是没有进程的”,Go协程的特点:

            1. 有独立的栈空间

            2. 共享程序堆空间

            3. 调度由用户控制

            4. 协程是轻量级的线程


        二、快速入门

            2.1、案例演示

            image.png

            image.png

            2.2、快速入门总结

            a、主线程是一个物理线程,直接作用在CPU上,是重量级的,非常耗费CPU资源

            b、协程是从主线程开启的,是轻量级的线程,是逻辑态的,对资源消耗相对较小

            c、golang的协程是重要的特点,可以轻松开启上万个协程,其他语言的并发机制一般是基于线程的;开启过多的线程,资源耗费大,这里就凸显golang在并发上的优势了

        三、Goroutine调度模型

            3.1、MPG基本模式介绍

            M(Machine):操作系统的主线程

            P(Processor):协程执行需要的资源(上下文context)

            G(Gorountine):协程,有自己的栈。包含指令指针(instruction pointer)和其它信息(正在等待的channel等等),用于调度。一个P下面可以有多个G

            image.png

            image.png

            3.2、MPG模式运行状态1

            image.png

            3.3、MPG模式运行状态2

            image.png

            3.4、设置golang运行的CPU数

            image.png


        四、channel(管道)

            4.1、完成下面需求

            image.png

            image.png

            执行ceshi.exe 结果如下:

            image.png

            

            存在问题的代码:

            image.png

            4.2、解决办法

            方法一:全局变量加锁同步改进程序

            image.png

            原理:

            image.png

            使用锁会用到的包:

            image.png

            代码改进:

            image.png

            image.png

            image.pngimage.pngimage.png

            方法二:channel通讯机制改进

            4.3、管道基本介绍

            image.png

            image.png

            4.3.1、管道示意:

            image.png

            image.png

            image.png

            4.3.2、管道基本使用

            声明/定义channel:

            var 变量名  chan 数据类型   !!!


            var perChan chan *Person

            var intChan  chan int

            var mapChan chan map[int]string    (用于存放map[int]string类型数据)

            说明:

            1.channel是引用类型

            2.channel必须初始化才能写入数据,即make后才能使用

            3.channel是有类型的,intChan 只能写入int类型数据

            

            演示管道的使用:

            image.png

            image.png

            4.3.3、channel使用注意事项

            a、channel中只能存放指定的数据类型

            b、channel中数据放满了就不能再往里面存放数据了

            c、如果从channel中取出数据以后就可以继续存放

            d、在没有使用协程的情况下,如果channel数据取完了,再取,就会报dead lock


            4.3.4、读写channel案例演示

            image.png

            image.png

            4.3.5、channel的遍历和关闭

            image.png

            image.png

            4.3.5、goroutine和channel协同工作

            需求:完成goroutine和channel协同工作

            1.开启一个writeData协程,向intChan中写入50个数据

            2.开启一个readData协程,从intChan中读取writeData写入的数据.

            注意:writeData和writeData操作的是同一个管道

            3.主线程需要等writeData和writeData协程完成工作才能退出

            image.png

            image.png

            image.png

            4.3.6、goroutine和channel  --  阻塞

            管道容量10,只向管道里面写入数据,写入50个数据,而没有读取,就会出现阻塞而deadlock!

            图1

            image.png

            图2

            image.png

            图3

            image.png

            图4

            image.png

            

            goroutine和channel应用3

            image.png

            思路分析:

            image.png

            代码:

            图一

            image.png

            图二

            image.png

            图三

            image.png


            4.4、channel使用细节和注意事项

            a、channel可以声明为只读,或者只写性质

            image.png

            image.png

            b、使用select可以解决从管道读取数据的阻塞问题

            基本语法:

            image.png

            image.png

            c、goroutine中使用recover, 解决协程中出现panic,导致程序崩溃的问题

            错误代码:

            image.png

            defer + recover

            image.png

            image.png












            


【原创】 第十四章、单元测试
11 03 2022

第十四章、单元测试

        一、基本介绍

            1.1、在工作中,我们经常会遇到这样的情况,就是去确认一个函数或者一个模块的结果是否正确,如:

            image.png

            1.2、传统方式测试

            在main函数中,调用addUpper函数,看看实际输出的结果是否和预期的结果一致,如果一致则说明函数正确,不一致则函数有问题

            案例:

            image.png

            分析:

            1、测试不方便, 我们要在main函数中去调用,这样就需要去修改main函数,如果项目正在运行,就有可能去停掉项目

            2、不利于管理,当我们测试多个函数或者多个模块时,都需要写在main函数,不利于我们管理和清晰思路

            3、引出单元测试,testing测试框架,可以很好的解决问题

            1.3、单元测试基本介绍

            image.png

            1.3.1、单元测试基本入门

            image.png

            image.png

            

            image.png

            1.3.2、单元测试基本原理


            image.png

            1.3.3、单元测试总结

            a、测试用例文件名必须以_test.go结尾,如:cal_test.go,cal不是固定的

            image.png

            b、测试用例函数必须以Test开头,一般来说就是Test+被测试的函数名,比如TestAddUpper(),Test后面的第一个字母必须大写

            c、TestAddUpper(t *testing.T)的参数类型必须是testing.T

            d、一个测试文件中可以有多个测试用例函数,比如TestAddUpper()   TestGetSub()等等   

            e、运行测试用例指令:

                命令行去到测试用例文件所在文件夹,执行go test,【如果运行正常,无日志;运行错误,输出日志】

                命令行去到测试用例文件所在文件夹,执行go test -v,【如果运行正常、错误,都会输出日志】

            f、当出现错误时,可以使用来格式化t.Fatalf() 输出信息,并退出程序

            g、t.Logf()方法可以输出相应日志        

            h、测试用例函数并没有放在main()函数中,也执行了,这就是测试用例函数的方便之处

            i、PASS表示测试用例运行成功,FAIL表示测试用例运行失败   

            j、测试单个文件,一定要带上被测试的源文件,go test -v cal_test.go cal.go

            image.png

            k、测试单个方法,go test -v  -test.run TestAddUpper

            image.png 

            1.3.4、单元测试综合案例_练习

            image.png

            代码:

            image.png

            image.png

            image.png

            image.png

            


【原创】 第十三章、文件的基本介绍
05 03 2022

第十三章、文件操作

        一、基本介绍

            1.1 概念

            文件在程序中是以流的形式来操作的

              image.png

            1.2 File文件位置

            在开发中操作文件,经常会用到os.File结构体

            image.png

            1.3 File文件读取操作

            a、打开文件

              b、关闭文件

            image.png

            c、读取文件并显示在终端(带缓冲区的方式)

            image.png

            d、直接读取文件内容

            image.png

            image.png

            1.4 File文件写操作

            a、使用带缓存的方式往文件中写入内容

            image.png

            image.png

            b、读取一个文件的内容,写入到另一个文件

            image.png

            1.5 判断文件或文件夹是否存在

            image.png

            1.6 将一个目录下的文件拷贝到另一个目录

            image.png

            1.7 os.Args存储所有的命令行参数

            image.png

            image.png

            1.8 使用flag包来解析命令行参数的用法

            image.png

            1.9 json基本介绍

            image.png

            1.9.1、json应用场景介绍

            image.png

            1.9.2、json工具站点:https://www.json.cn/

            1.9.3、json的序列化

            image.png

            1.9.4、json的序列化案例演示

            image.png

            image.png

            

            image.png

            image.png

            1.9.5、json的tag标签的使用

            image.png

            1.9.6、json反序列化

            image.png

            案例演示

            image.png

            image.png

            说明:

            1. 在反序列化一个json字符串时,要确保反序列化后的数据类型和原来反序列化前的数据类型一致,比如结构体,字段数量和名字保持一致,不能多不能烧

            2. 如果json字符串是通过程序获取到的,则不需要再 " 转义处理了。

            image.png



【原创】 Win10环境下安装redis5.0.10
16 02 2022

Windows环境下安装redis

        1、安装Redis客户端

            1.1 下载地址:https://github.com/tporadowski/redis/releases

            1.2 redis指令地址:http://redisdoc.com/

        2、开启Redis服务

            2.1 来到redis解压目录,使用命令cmd进入到命令行窗口

            image.png

            2.2 开启redis服务

            image.png

            image.png

        3、下载redis扩展

            3.1 下载地址:http://pecl.php.net/package/redis

            下载版本根据安装的客户端redis版本选择

            image.png

            3.2 点击版本厚点的DLL,下载另一个扩展

            image.png

            image.png

            根据上图PHP版本选择下载扩展

            image.png

        4、安装扩展

            4.1 解压扩展,复制到:D:\wamp326\bin\php\php7.3.33\ext目录下

            image.png

            image.png

            4.2 修改php.ini文件,在如下位置添加extension=php_redis.dll重启

            image.png

        5、重启wampserver服务

            5.1 访问phpinfo()搜索redis,发现如下扩展则安装成功

            image.png

        6、windows环境下的开机自启动

            6.1 启动redis服务,进入到redis安装目录,输入命令:  redis-server.exe redis.windows.conf

            image.png

            6.2 打开一个新的cmd,输入命令:   redis-server --service-install redis.windows.conf

           image.png 

            6.3 重启,查看计算机服务

            image.png

            6.4 启动一个客户端,测试redis服务

            image.png

            6.5 自启动与关闭自启动:

            redis-server --service-start

            image.png

            redis-server --service-stop

            image.png

           image.png

        7、使用PHP连接redis

            7.1 PHP连接redis测试

            image.png

            image.png


【原创】 第十二章、面向“对象”编程
28 12 2021

第十二章、面向“对象”编程

        一、结构体

            1.1 概念

            一个程序就是一个世界,有很多对象(变量)

            1.2 golang语言面向对象编程说明

            a、golang也支持面向对象编程(oop),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言,所以我们说golang支持面向对象编程特性是比较准确的。

            b、golang没有类(class),go语言的结构体(struct)和其他编程语言的类(class)有同等的地位,可以理解golang 基于struct来实现OOP特性的。

            c、golang面向对象编程非常简介,去掉了传统语言的继承、方法重载、构造函数和析构函数,隐藏的this指针等等

            d、golang仍然有面向对象编程的继承、封装和多态特性,只是实现的方式和其他OOP语言不一样,比如继承:golang没有extends关键字,是通过匿名字段来实现的

            e、golang面向对象(OOP)很优雅,OOP本身就是语言类型系统的一部分,通过接口(interface)关联,耦合性低,也非常灵活。

            1.3 结构体

            

image.png


            对上图说明:

            a、将一类事务的特性提取出来(比如猫),形成一个新的数据类型,就是一个结构体

            b、通过这个结构体,我们可以创建多个变量(实例/对象)

            c、事务可以是人类、商品、工具类...

            1.3 结构体和结构体变量的区别联系

            a、结构体是自定义的数据类型,代表一类事物

            b、结构体变量是具体的、实际的、代表一个具体变量

            1.4 结构体在内存的布局

            声明未赋值:

            image.png

            结构体赋值以后:

            image.png

            1.5 如何声明结构体

            1.5.1、声明

            image.png

            1.5.2、字段/属性

            a、从概念或者叫法上看:结构体字段=属性=field

            b、字段是结构体的一个组成部分,一般是基本数据类型、数组、也可以是引用数据类型,比如前面我们定义的猫猫结构体,Name string就是属性

            1.5.3、字段/属性注意事项(结构体是值类型!!!)

            image.png

            注意事项3:

            image.png

            注意事项4:不同结构体字段是独立的,互不影响

            image.png

            image.png

            画出上面代码的内存示意图:

            第一步、值拷贝

            image.png

            第二步、修改值

            image.png

            1.5.4、创建结构体变量和访问结构体字段

            image.png

            image.png

            image.png

            image.png

            image.png

            image.png

            image.png

            1.5.5、struct类型的内存分配机制

            image.png

            image.png

            image.png

            1.5.6、结构体的注意事项和使用细节

            a、结构体的所有字段在内存中 是连续的

             image.png

            b、结构体是用户单独定义的类型,和其他类型转换时需要有完全相同的字段(名字、个数和类型)

            image.png

            c、结构体进行type重新定义(相当于取别名),golang认为是新的数据类型,但是互相间可以强转

            image.png

            d、struct的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和烦序列化

            image.png

            image.png

            案例演示:

            image.png

            image.png


        二、方法

            2.1 基本介绍

            image.png

            2.2 方法的声明和调用

            image.png

            image.png

            上面代码说明:

            a、func (a A) test(){}    表示A结构体有一个方法,方法名test

            b、(a A) 体现test方法和A类型绑定

            案例演示:

            image.png

            对上面代码总结:

            a、test()方法和类型Person5绑定

            b、test()方法只能通过Person5类型的变量来调用,而不能直接调用,也不能使用其他类型变量来调用

            c、func(p Person5)test(){},  p表示哪个Person5变量调用,这个p就是它的副本,这点和函数的传参非常相似

            d、p这个名字,由程序员指定,不固定

            练习案例:

            1.

            image.png

            image.png

            2.

            image.png

            image.png

            2.3 方法的调用和传参机制

            说明:方法的调用、传参机制和函数基本一样,不一样的地方是方法调用时,会将调用方法的变量,当做实参也传递给方法

            image.png

            image.png

            image.png

            2.4 方法注意事项和细节

            a、结构体类型是值类型,在方法调用中,遵守值类型传递机制,是值拷贝传递方式

            b、如果程序员希望在方法中,修改结构体变量的值,可以通过结构体指针的方式来处理,通常也多用指针方式,程序运行效率更高

            image.png

            内存说明:

            image.png

            c、golang中的方法作用在指定类型上,(即:和指定的数据类型绑定),因此,自定义类型都可以有方法,而不仅仅是struct,比如int、float64等等都可以

            image.png

            d、方法的访问范围控制规则,和函数一样。方法名首字母小写,只能在本包访问,方法名首字母大写,可以在本包和其他包函数访问

            e、如果一个类型实现了String()这个方法,那么fmt.Println默认会调用这个类型的String()进行输出,一般可以用在日志记录

            image.png

            2.5 方法和函数的区别

            a、调用方式不一样

            函数的调用方式:函数名(实参列表)

            方法的调用方式:变量.方法名(实参列表)

            b、对于普通函数,接收者为值类型时,不能将指针类型的数据传递,反之亦然

            image.png

            c、对于方法,接受者为值类型时,可以直接用指针类型的变量调用方法,反过来同样可以

            image.png

            image.png

            image.png

        三、面向对象编程应用实例

            3.1 步骤

            image.png

            3.2 创建结构体变量时指定字段值

            image.png

            3.3 工厂模式

            image.png

            image.png

            image.png

            工厂模式解决结构体中结构体名字首字母小写问题::

            image.png

            image.png

            如果结构体student的age字段首字母也是小写,在其他包不可以直接访问,我们可以提供一个方法

            image.png

            image.png

            3.4 面向对象编程思想-抽象

            简介:

            image.png

            案例演示:

            image.png

            image.png

            image.png

            3.5 面向对象编程的三大特性

            3.5.1 基本介绍

            golang仍然有面向对象编程的继承、封装、多态的特性,只是实现的方式和其他的OOP语言不一样

            3.5.2 封装:封装就是把抽象出来的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作(方法),才能对字段进行操作

           image.png 

            封装的实现步骤:

            1、将结构体、字段的首字母小写(不能导出,其他包不能使用,类似private)

            2、给结构体所在的包提供一个工厂模式的函数,函数名首字母大写,类似一个构造函数

            3、提供一个首字母大写的Set方法

            image.png

            4、提供一个首字母大写的Get方法

            image.png

            特别说明:在golang开发中并没有特别强调封装,这点并不像java、PHP,golang本身对面向对象的特性做了简化的

            案例:

            image.png

            image.png


            3.5.3 继承:当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出这些结构体,在该结构体中定义相同的属性和方法,其他的结构体不需要重新定义这些相同的属性和方法,只需要嵌入一个(基础结构体的)匿名结构体就可以了;也就是说,一个结构体嵌套了另一个匿名结构体,那么这个结构体就可以直接访问匿名结构体的属性和方法,从而实现继承特性

            画图说明继承的特性:

            image.png

            嵌套匿名结构体的基本语法:

            image.png

            案例演示:

            image.png

            image.png

            继承给编程带来的便利:

            a、代码的复用性提高了

            b、代码的扩展性和维护性提高了

            继承深入讨论:

            a、结构体可以使用嵌套匿名结构体的所有字段和方法,即:首字母大写、小写的字段 方法都可以使用, 注意::但是跨包不能访问小写字段和方法

            b、匿名结构体字段访问可以简化

            image.png

            上图代码说明:

            image.png

            c、当结构体和匿名结构体有相同的字段或方法时,编译器采用“就近原则”访问,如果希望访问匿名结构体的子弹和方法,可以通过匿名结构体来区分

            d、当结构体嵌入多个匿名结构体...

            image.png


            e、如果一个struct嵌套了一个"有名结构体",这种模式就是“组合”,如果是组合关系,那么在访问组合的结构体方法或字段时,必须带上结构体的名字 

            image.png

            f、嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值


            image.png

            image.png

            指针方式:

            image.png

            image.png

            g、结构体中匿名字段使用

            image.png


        四、接口

            4.1.1 golang接口简介

            interface类型可以定义一组方法,但是这些方法不需要实现,并且interface不能包含任何变量,到某个自定义类型(比如下面列子的结构体Phone)要使用的时候,再根据具体情况把这些方法写出来(实现)。

            image.png

            4.1.2 基本语法

            image.png

            image.png

            4.1.3 为什么会有接口

            image.png

            4.1.4 入门案例演示

             image.png

            image.png

            image.png

            4.1.5 接口注意事项和细节说明

            a、接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)

            image.png

            b、接口中所有的方法都没有方法体,即:都是没有实现的方法

            c、在golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口

            d、只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型

            image.png

            image.png

            e、一个自定义类型可以实现多个接口

            image.png

            image.png

            f、golang接口中不能有任何变量,编译不过,会报错

            g、一个接口(比如A接口),“可以继承多个”别的接口(比如B、C接口),这时如果要实现A接口,必须将B、C接口的方法全部实现

            image.png

            image.png

            h、interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil

            i、空interface{}没有任何方法,所以,所有类型都实现了空接口(换句话说就是,我们可以把任何数据类型的变量赋值给空接口)

            image.png

            image.png

            4.1.6 接口编程实践

            image.png

            image.png

            4.1.7 实现接口 vs 继承

            image.png

            案例演示:

            image.png

            image.png

            说明:

            a、当结构体B继承了结构体A,那么结构体B就自动的继承了结构体A的字段和方法,可以直接使用

            b、当B结构体需要扩展功能,同时不希望破坏继承关系,则可以去实现接口,因此我们认为:实现接口是对继承的补充!!!

            4.1.8 接口 和 继承的区别

            image.png


        五、面向对象编程-多态

            5.1.1 基本介绍

            变量(实例)具有多种形态,在go语言中,多态特征是通过接口来实现的,可以按照统一的接口来调用不同的实现,这时接口变量就呈现不同的形态。

            5.1.2 接口体现多态的两种形式

            image.png

            案例演示:

            image.png

            image.png

            5.1.3 类型断言基本介绍

            类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,就需要使用类型断言

            image.png

            如何在断言时,带上监测机制,如果成功就ok,否则也不要报panic

            image.png

            5.1.4 类型断言实践

            第一题、usb接口案例

            image.png

            image.png

            第二题、写一个函数, 循环判断传入参数的类型

            image.png

            image.png


【原创】 第十一章、go内置函数
08 12 2021

第十一章、go内置函数以及错误处理

        11.1 go内置函数

                1、内置函数简介

                golang设计者为了编程方便,提供了一些函数,这些函数可以直接使用,我们称之为内置函数(也叫内建函数),https://studygolang.com/pkgdoc -> builtin包

                2、一些常用内置函数

                len()函数

                image.png

                new()函数:用来分配内存,主要用来分配值类型,比如:int、float、struct...  返回的是指针 

                image.png

                内存分配示意图:

                image.png

                image.png

                make()函数:用来分配内存,主要是用来分配引用类型,比如chan、map、slice


        11.2 golang错误处理

                11.2.1 看一段代码

                image.png

                说明:

                a、在默认情况下,当发生错误(panic)后,程序就会退出(崩溃)

                b、如果我们希望:在发生错误后可以捕捉到错误,并进行处理保证程序可以继续执行,可以在捕捉到错误以后,给管理员发送邮件或者短信...

                c、这里引出错误处理机制

                

                11.2.2 golang错误处理基本说明

                image.png

                案例:

                image.png

                错误处理的好处:进行错误处理后,程序不会轻易挂掉,如果加入预警代码,就可以让程序更加的健壮


        11.3 自定义错误处理

                11.3.1 在go中也支持自定义错误,使用errors.New和panic内置函数

                第一步、errors.New("错误说明"),会返回一个error类型的值表示一个错误

                第二步、panic内置函数,接收一个interface{}类型的值(也就是任何值)作为参数,可以接收error类型的变量,输出错误信息,并退出程序

                image.png

                

                




                

【原创】 第十章、go中常用函数
03 12 2021

第十章、go中常用函数

        10.1 字符串中常用系统函数

                1、统计字符串长度(字节),len(str)

                image.png

                2、统计字

                字符串遍历,同时处理有中文的问题  r:=[]rune(str)

                image.png

                3、字符串转整数  n,err := strconv.Atoi()

                image.png

                4、整数转字符串  str := strconv.Itoa(632)

                image.png

                5、字符串转[]byte    var bytes = []byte("abds")

                image.png

                6、[]byte转字符串   str := string([]byte{97,98,99})

                image.png

                7、十进制转2,8,16进制   str = strconv.FormatInt(i int64, base int) string

                image.png

                8、查找子串是否在指定的字符串:

                image.png

                image.png

                9、统计一个字符串有几个指定的子串   strings.Count("cheseese","e")

                image.png

                10、不区分大小写的字符串比较(==是区分字母大小写的)    strings.EqualFold("ab","Ab")

                image.png

                image.png

                11、返回子串在字符串第一次出现的index值(位置),如果没有返回-1   strings.Index("FDJ_abc","abc")

                image.png

                12、返回子串在字符串最后出现的位置,如果没有则返回-1  strings.LastIndex("go golanmg","go")

                image.png

                13、将指定的子串替换成另一个子串strings.Replace("go go go hello","go","go语言",n),n可以指定你希望替换几个,如果n<0 表示全部替换

                image.png

                14、按照指定的某个字符 为分割标识符,将一个字符串拆分成字符串数组strings.Split("hello,world,ok",",")

                image.png

                15、将字符串的字母进行大小写转换strings.ToLower("Go") //strings.ToUpper("Go") //GO

                image.png

                16、将字符串左右两边的空格去掉 strings.TrimSpace(" ds a long ntr ")

                image.png

                17、将字符串左右两边指定的字符去掉strings.Trim("! hello !"," !")

                image.png

                18、将字符串左边指定的字符去掉strings.TrimLeft("!hello!","!")

                image.png

                20、判断字符串会否以指定的字符串开头strings.HasPrefix("ftp://192.168.3.1","ftp") //true

                image.png

                21、判断字符串会否以指定的字符串结尾strings.HasSuffix("qaq.jpg","jpg")

                image.png


        10.2 时间和日期相关函数

                10.2.1、简介:时间和日期相关函数,需要导入time包

                10.2.2、time.Time类型用于表示时间

                image.png

                10.2.3、获取其他的日期信息

                image.png

                10.2.4、格式化日期和时间

                a、使用Printf或者Sprintf

                image.png

                b、Format函数格式化

                说明:

                使用format函数,参数“2006/01/02 15:04:05”这个字符串是固定式,必须这样写,据网上流传是go语言设计者想设计一门新语言想法的最初时间;这个字符串的格式可以改变,但是数字数据不能改变

                image.png

                10.2.5、时间的常量

                image.png

                不能在时间单位后面去除一个数 ,只能用时间单位乘以一个数字来表示要表达的时间

                案例演示,配合sleep(休眠)做如下练习,func Sleep(d Duration) time.Sleep(100 * time.Millisecond) 表示100毫秒

                image.png

                10.2.6、获取当前unix时间戳和unixnano时间戳(作用是可以获取随机数字)

                image.png

                练习:

                image.png

                


                



                

【原创】 第九章、函数
29 11 2021

第九章、函数

        9.1 函数基本介绍

                函数是为完成某一功能的程序指令(语句)的集合,称为函数。在go中,函数分为自定义函数和系统函数。

        9.2 函数基本语法

                基本语法如下:   

                image.png

                案例:

                image.png

        9.3 go中的包

                9.3.1 包的基本概念

                go的每一个文件都是属于一个包的,也就是说go是以包的形式来管理文件和项目目录结构的

                9.3.2 包的引出

                在实际的开发中,我们往往需要在不同的文件中,去调用其他文件定义的函数,比如在main.go中去使用utils.go中的函数  

                9.3.3 包的原理

                包的本质:实际上就是创建不同的文件夹,来存放程序文件

                image.png

                

                image.png

                9.3.4 包的三大作用

                a、区分相同名字的函数、变量等标识符

                b、当程序文件较多时,可以很好的管理项目

                c、控制函数、变量等访问范围,即作用域

                9.3.5 打包基本语法

                package 包名

                9.3.6 引入一个包

                import "包的路径"

                9.3.7 包的快速入门,调用包中的函数

                案列:

                image.png


                image.png


                image.png

                9.3.8 包的注意事项和细节说明

                image.png


                image.png


                image.png

        9.4 函数的调用机制

                9.4.1 基本介绍

                image.png

                image.png

                9.4.2 golang中,函数调用机制的底层分析

                image.png

                1. 第一步,主函数n1赋值,主函数中去调用test()函数;在调用一个函数时,会给该函数分配一个新的空间,编译器会通过自身的处理让这个新的空间和其他栈的空间区分开来

                image.png

                2. 第二步,test()函数执行完毕,终端输出n1=11,编译器回收test()函数里面的变量;在每个函数对应的栈中,数据空间是独立的,不会混淆;当一个函数执行完毕,程序会销毁这个函数对应的栈空间

                image.png

                3. 第三步,main()函数也执行完毕,终端输出test()中的n1=11,main()函数的n1=10,编译器回收main()函数里面的n1变量

                image.png

                9.4.3 案例演示

                image.png

                9.4.4 函数中return 语句介绍

                image.png

        9.5 递归函数

                9.5.1 递归函数简介

                一个函数在函数体内又调用了本身,我们称为递归调用

                案例演示:

                image.png

                过程分析图:

                image.png

                递归调用的总结:

                image.png

                9.5.2 递归练习题

                练习1:请使用递归的方式,求出斐波拉契数    1,1,2,3,5,8,13,21...

                image.png

                练习2:习题如下

                image.png

        9.6 函数注意事项和细节讨论

                image.png

                image.png 

                image.png

                案例演示第6:

                image.png

                第一步、

                image.png

                第二步、

                image.png

                案例演示第6、第8:

                image.png

                案例演示第10:

                image.png

                案例11:

                image.png

                image.png

                案例演示第13:

                image.png

        9.7 init函数

                9.7.1 基本介绍

                每一个源文件都可以包含一个init函数,该函数会在main函数之前执行,被go运行框架调用,也就是说init函数会在main函数之前被调用

                9.7.2 案例演示

                image.png

                9.7.3 细节讨论

                a、如果一个文件同时包含init函数、main函数、全局变量定义,则执行的流程顺序是全局变量定义 -> init函数 -> main函数

                image.png

                a、init函数的主要作用,就是完成一些初始化工作

                案例如下:

                image.png

                image.png

                a、如果主函数main.go  和初始化函数init.go中都含有变量定义,执行的流程又是怎么样的呢?

                image.png

                image.png

        9.8 匿名函数

                9.8.1 基本介绍

                Go支持匿名函数,如果我们某个函数只希望使用一次,可以考虑使用匿名函数匿名函数也可以实现多次调用

                9.8.2 匿名函数使用方

                使用式1:

                在定义匿名函数时就直接调用这种方式匿名函数只能调用一次

                image.png

                使用式2:

                将匿名函数赋值给一个变量(函数变量),再通过该变量来调用匿名函数

                image.png

                9.8.3 全局匿名函数

                如果将匿名函数赋值给一个全局变量,那么这个匿名函数就是一个全局匿名函数

                image.png

                image.png

        9.9 闭包函数

                9.8.1 基本介绍

                闭包就是“一个函数”和“与其相关的引用环境”组合的“整体(实体)”

                9.8.2 案例演示1

                image.png

                对上面代码说明和总结:

                1、AddUpper()是一个函数,返回的数据类型是 func(int) int

                2、闭包的说明:返回的是一个函数, 返回的是这个匿名函数,但是和这个匿名函数引用到了函数外面的变量n,因此这个匿名函数就和n形成一个整体,构成闭包

                image.png

                3、可以这样理解:闭包是一个类,函数是操作,n是字段,函数和它使用到的n构成闭包

                4、当我们反复调用f函数时,因为n是初始化一次,因此每调用一次就进行累计

                5、我们要搞清楚闭包的关键,就是要分析出返回的函数它使用(引用)到哪些变量,因为函数和它引用到的变量共同构成闭包

                案例演示2

                image.png    

                代码说明:返回的匿名函数和makeSuffix(suffix string)的suffix变量组成一个闭包,因为返回的函数引用到suffix这个变量            

                闭包的好处:闭包可以把匿名函数引用到的变量保存(引用)下来,进行下次调用回

        9.10 函数中的defer

                9.10.1 基本介绍

                在程序中,程序员经常需要创建资源,(比如:数据库链接、文件句柄、锁等~),为了再函数执行完毕后,及时的释放资源,go的设计者提供defer延时机制

                9.10.2 案例说明

                image.png

                9.10.3 defer细节说明

                a、当go执行到一个defer时,不会立即执行defer后的语句,而是将defer后的语句压入到一个栈中,然后继续执行函数下一个语句

                b、当函数执行完毕以后,再从defer栈中依次从栈顶取出语句执行,注意:(入栈先入后出机制)

                c、在defer将语句入栈时,也会将相关的值拷贝同时入栈!!! 

                image.png

                d、函数中,defer的最佳实践!!!!!!!!!!

                image.png

                image.png

        9.11 函数参数的传递方式

                9.11.1 基本介绍

                值类型默认就是值传递,而引用类型参数默认就是引用传递

                其实,不管是值传递还是引用传递,传递给函数的都是变量的副本,不同的是值传递的是值的拷贝,而引用传递的是地址的拷贝,一般来说,地址拷贝效率高,因为数据量小,而值拷贝决定拷贝的数据大小,数据越大,效率越低

                9.11.2 值类型和引用类型

                值类型:基本数据类型int系列、float系列、bool、string、数组和结构体struct

                引用类型:指针、slice切片、map、管道chan、interface等都是引用类型

                image.png

                3)如果希望函数内的变量能改变函数外的变量,可以传入变量的地址,(&num),函数内以指针的方式操作变量

        9.12 变量作用域

                9.12.1 基本介绍

                a、函数内部声明/定义的变量叫局部变量,作用域仅限于函数内部 

                b、函数外部声明/定义的变量叫全局变量,作用域在整个包都有效,如果其首字母大写,在整个程序有效

                9.12.2 案例演示

                image.png

                注意:::

                image.png

                image.png



【原创】 第八章、Golang程序流程控制语句
24 11 2021

第八章、程序流程控制

        8.1、程序流程控制介绍

                图片.png

        8.2、顺序结构语句

                图片.png

        8.3、分支结构语句

                图片.png

                8.3.1 单分支结构

                基本语法如下:

                图片.png

                举例:

                图片.png

                注意事项:

                go 语句的if 后面必须是一个条件表达式,不能是赋值语句

                图片.png

                图片.png

                image.png

                8.3.2 双分支结构

                基本语法如下:

                图片.png

                举例:

                图片.png

                8.3.3 多分支结构

                基本语法如下:

                图片.png

                流程图:

                图片.png

                案例:

                图片.png

                图片.png

                注意事项:多分支流程图中 任何时候只会有一个分支会有输出结果,走到那一块就结束了

                图片.png

                8.3.4 多分支结构

                图片.png

                举例:

                image.png

        8.4、switch分支结构语句

                8.4.1 switch简介

                image.png

                image.png

                8.4.2 switch流程图

                image.png

                8.4.3 举例

                image.png

                8.4.4 注意事项:

                image.png

                注意:

                image.png

                image.png

                image.png

                image.png

                image.png

                image.png

                8.4.5 switch和if的比较

                image.png

        8.5、for循环控制语句

                8.5.1 for循环语句简介

                image.png

                8.5.2 for循环流程图

                image.png

                8.5.3 for循环使用细节

                image.png

                8.5.4 举例

                image.png

                image.png

                image.png

        8.6、go中没有while和do...while的实现

                image.png              

                8.6.1 for循环实现while效果

                image.png

                案例:

                image.png

                8.6.2 for循环实现do...while效果

                image.png

                image.png

                案例:

                image.png

        8.7、多重循环

                8.7.1 基本介绍

                image.png

                案例1:

                image.png

                案例2:

                image.png

                image.png

                代码如下:

                image.png

                image.png

        8.8、跳转控制语句break

                8.8.1 基本语法介绍

                image.png

                8.8.2 流程图

                image.png

                8.8.3 案例

                image.png

                8.8.4 break使用细节

                image.png

                image.png

                说明:

                break 默认跳出最近的一层for循环

                break 后面可以指定标签,跳出标签对应的for循环

        8.9、跳转控制语句continue

                8.9.1 基本语法介绍

                continue语句用于结束本次循环,继续执行下一次循环

                image.png

                8.9.2 continue流程图

                image.png

                8.9.3 案例

                image.png

        8.10、跳转控制语句goto

                8.10.1 基本介绍

                image.png

                8.10.2 案例

                image.png

        8.11、跳转控制语句return

                8.11.1 基本介绍

                return使用在方法或者函数中,表示跳出所在的方法或函数。

                说明:

                1、 如果return是在普通的函数中,则表示跳出该函数,既不再执行函数中return后面的代码,也可以理解成终止函数。

                2、如果return是在main函数,表示终止main函数,也就是说终止程序。

                image.png

【原创】 第七章、Golang运算符
23 11 2021

第七章、Golang运算符

        1、Go语言运算符

            1.1 基本介绍

                介绍:运算符是一种特殊的符号,用于数值的运算、赋值、比较等.

                算术运算符:                   + - * / 取模

                赋值运算符:                   = += -= *= /= 

                比较运算符/关系运算:    == != >=  <= > <

                逻辑运算符:                   与 或 非

                位运算符:                      位与   位或  位异或  位左移   位右移

                其他运算符:                   取址运算符 &    取值运算符 *

            1.2 算术运算符

                介绍:对数值类型的变量进行运算,如加减乘除

                图片.png

                演示/的使用:

                图片.png

                演示%的使用:

                图片.png

            1.2.1 算术运算符使用注意事项

    a、对于除号 "/",它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。  例如:  x := 19/5 ,结果是3

                b、当对一个数取模时,可以等价 a%b = a-a/b*b  , 这样我们可以看到 取模的一个本质运算。

                c、对Golang 的自增自减只能当做一个独立语言使用时,不能这样使用 b := a++  或者 b := a--

                d、Golang的++和--只能写在变量的后面,不能写在变量的前面, 没有 --a   ++a 这样的写法

                图片.png

                e、Golang设计者去掉了C/java中容易混淆的自增自减的写法,让Golang 更加简介 统一

            1.2.2 算术运算符练习

                图片.png

            1.3 关系运算符(比较运算符)

                介绍:关系运算符的结果都是bool型,要么是true 要么是false

                          关系表达式经常用在if结构的条件中或循环结构的条件中

                图片.png

            1.3.1 关系运算符使用细节

                a、关系运算符的结果都是bool型,要么是true 要么是false

                b、关系运算符组成的表达式,我们称为关系表达式,如 a > b

                c、比较运算符"==" 不能写成 "="

            1.4 逻辑运算符

                介绍:用于连接多个条件(一般来讲就是关系表达式),最终的结果也是bool值

                图片.png

                练习:

                图片.png

            1.4.1 逻辑运算注意事项和细节说明

                  &&也叫短路与,如果第一个条件为false,则第二个条件不会判断,结果为false

                  ||也叫短路或,如果第一个条件为true,则第二个条件也不会判断,结果为true 

            1.5 赋值运算符

            1.5.1 赋值运算符介绍

                图片.png

                图片.png

            1.5.2 例子

                图片.png

            1.5.3 赋值运算符特点

                a、运算顺序从右到左

                b、赋值运算符的左边只能是变量,右边可以是变量、表达式、常量值等


            1.6 运算符优先级

                图片.png


            1.6.1 位运算符

                图片.png

                golang中的位运算符:

                图片.png

                举例:

                图片.png

                计算过程:

                图片.png

                移位注意事项:

                图片.png



            1.6.2 位运算符

                图片.png


                举例实现三元运算符效果:

                图片.png


            1.7 键盘输入语句

            1.7.1 介绍:在开发中,需要接收到用户输入的数据,就需要使用键盘输入语句来获取

            1.7.2 步骤

                a、导入fmt包

                b、调用fmt包的函数,fmt.Scanln()  或者fmt.Scanf()

            1.7.3 需求:从控制台接收用户信息,年龄、姓名、薪水、是否通过考核

                方式一、fmt.Scanln()

                图片.png

              方式二、fmt.Scanf()

                图片.png

            1.8 计算机基础进制转换

                1.8.1 基数简介

                进制其实就是基数,大于或等于基数时,向高位进1。10进制基数就是10,二进制基数就是2,八进制(8)、十六进制(16)。

                图片.png

                1.8.2 原码、反码、补码

                图片.png



【原创】 PHP面试积累
21 11 2021

PHP的一些面试题以及基础知识

        1、PHP中字符串和数字加减

            1.1、7.0及以下版本

            echo "1" + 1 、echo "1" - 1 ,解析成数字参与运算;

            echo "9fdd" - 1 字符串中第一位是数字,在运算时候,会解析字符串中第一个数字参与运算,数字以后的字符忽略;

            echo "fd6fdf" - 1 会直接忽略整个字符串,输出 - 1 ;

             5.6.png

            

            7.0.png

            1.2、7.1及以上版本

            echo "1" + 1 、echo "1" - 1 ,解析成数字参与运算;

            echo "9fdd" - 1,会输出8,但是会提示语法错误;

            echo "fd6fdf" - 1 ,忽略字符串部分,直接输出 - 1, 并且语法有警告错误;

            

            


            


            


        2、PHP是单线程还是多线程

            image.png

        3、如何保证token不被盗用?

        ① app端

        前端第一次请求登录的时候把ip地址或者设备id携带过来(就只有第一次),保存在后数据库或者redis缓存中,后面的请求token对应的ip地址或者设备id不一样,则视为非法请求。出现非法请求以后,必须使用注册的手机号进行验证码验证,验证通过则解除安全提示(原来的token过期不再使用),否则不让登录。(最好是携带设备id,因为ip有可能换流量换WIFI等.)

        4、php中isset()函数和empty()函数的区别?

        ① 共同点

        都可以判断一个变量是否为空;都返回布尔型,即 true  或 false

        ② 不同点

        empty() 判断一个变量是否被认为是空的。当一个变量并不存在,或者它的值等同于 FALSE,那么它会被认为不存在。如果变量不存在的话,empty()并不会产生警告;empty() 5.5 版本之后支持表达式了,而不仅仅是变量。

        isset() 函数用于检测变量是否已设置并且非 NULL。如果已经使用 unset() 释放了一个变量之后,再通过 isset() 判断将返回 FALSE。若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。同时要注意的是 null 字符("\0")并不等同于 PHP 的 NULL 常量。





【原创】 韭黄肉丝
14 11 2021

        这一次的周末两天时间几乎没出门,想起了冰箱里还有冻到的肉丝,今天就它了“韭黄肉丝”,虽然比不过仔姜肉丝,但依然巴适得板

        继续往下看,以下是配菜和做菜全过程。

        配菜:

        一部分大蒜切片,一部分大蒜和老姜切成碎末增加香味,泡的小米辣5个,冬天买不到仔姜用一坨泡的嫩姜代替也可以,韭黄一把,二荆条5~10个,肉丝切成细细的一小条一小条(特别费时),肉丝切得太粗糙那就不叫肉丝了。肉丝切好以后,弄一小勺红薯粉,半盖子白酒,一个鸡蛋清放在肉丝里反复抓匀备用。



韭黄肉丝1.jpg


韭黄肉丝2.jpg



        过程:

        起锅烧油,锅热关小火,先炒一下小米辣、姜丝、大蒜老姜末,炒香出锅备用。开大火,锅里放油,炒肉丝油要多一点,油热关小火,放肉丝翻炒,放刚才炒好备用的小米辣,放一勺郫县豆瓣酱,不够可以再多半勺,一定要把肉丝炒出红油,开大火放二荆条反复翻炒,这个时候再来一盖子白酒去味,肉丝炒熟马上放韭黄、盐、味精、鸡精翻炒均匀,出锅装盘,开始享受晚餐!


韭黄肉丝3.jpg

       

韭黄肉丝5.jpg






【原创】 酸菜鱼
13 11 2021

        今天,2021年11月13号,已经很久很久没有更新文章更新做菜了,今天的一道新菜酸菜鱼是今年我学会的第四道菜,完成了一个季度学会一样菜的目标,这里应该有掌声!!!

        继续往下看,以下是配菜和做菜全过程。

        配菜:

        野山椒切短节、酸菜、一部分大蒜切片、一部分大蒜和老姜切成末、干辣椒、葱花、一条2斤草鱼切薄片,接下来很重要的一步,腌制鱼,打两个鸡蛋清、半勺盐、半盖子白酒、一勺红薯粉,一起抓匀腌制5分钟。



酸菜鱼1.png


酸菜鱼2.png



        过程:

        起锅烧油,油热关小火,把大片的鱼头和鱼骨头先煎炒,煎炒一分钟捞出,锅里留油,放酸菜、野山椒、大蒜老姜末翻炒,放花椒、藤椒油继续翻炒,翻炒香以后放一碗半冷水煮开,煮开之后先下鱼头和大片的鱼骨头,记得放一盖子白酒,煮三分钟左右捞出鱼头和鱼骨头,捞出鱼骨头以后放盐、味精、鸡精,锅里搅拌均匀,搅拌以后立马下鱼片,鱼片2到3分钟即可煮熟捞出装盘,鱼片表面撒上干辣椒,锅里再烧热油,油开淋在辣椒表面,撒上葱花,开始享受晚餐!


酸菜鱼3.png

       

酸菜鱼4.png


酸菜鱼5.png


【原创】 第六章、Golang标识符
20 10 2021

第六章、Golang标识符

        1、标识符的命名规范

            1.1 基本介绍

                a、对Golang对各种变量、方法、函数等命名时使用的字符序列称为标识符

                b、凡是自己可以起名字的地方都叫标识符,比如:var num int    var name string都是标识符

            1.2 标识符的命名规则

                a、由26个大小写英文字母、0-9、_组成

                b、数字不能开头

                c、golang中严格区分大小写

                d、标识符不能包含空格

                e、下划线“_”本身在go中是一个特殊的标识符,称为空标识符,可以代表其他任何的标识符,但是它对应的值会被忽略(比如忽略某个返回值),所以仅能被作为占位符使用,不能作为标识符使用

                f、中文在go中定义变量的时候不会报错,编译也通过,但是定义go变量的时候不推荐使用中文

                图片.png

                f、不能以系统保留的关键字作为标识符,比如 if 、break等等...

                图片.png

            1.3 标识符案列

                  图片.png 

            1.4 标识符命名注意事项

                a、包名:保持package的名字尽量和目录一致,尽量采用有意义的包名;简短有意义,不要和标准库冲突

                图片.png

                b、变量名、函数名、常量名:采用驼峰法,比如:var  studentName string = "暗夜猎手薇恩";  var goodsPrice float64 = 15.5

                c、如果变量名、函数名、常量名首字母大写,则可以被其他的包访问,如果首字母小写,则只能在本包中使用(注:可以理解成,首字母大写是公有的,首字母小写是私有的,其他编程语言的关键字public、 pricate、protected...  golang中没有public、 pricate、protected...等关键字

                例子:

                图片.png

                

                图片.png


        2、系统保留关键字

                图片.png

        3、系统的预定义标识符

                图片.png


【原创】 第五章、Golang派生/复杂数据类型
15 10 2021

第五章、Go派生/复杂数据类型

        1、指针类型

            1.1 基本介绍

                a、对于基本类型来说,变量存的就是值,也叫值类型,基本数据类型在内存中的布局如下:

                图片.png

                b、获取变量的地址,使用&符号。比如,var i int = 10,获取i的地址:&i

                c、指针类型,指针变量存的是一个地址,这个地址指向的空间才是存的值;比如:var ptr *int = &num     在这里,带了* ptr是一个指针,没带*,ptr是整数。举例:指针在内存的布局

                图片.png

                d、获取指针类型所指向的值,使用 *,比如:var ptr *int ,使用*ptr获取ptr指向的值

                图片.png

            1.2 案例演示

                1.2.1 写一个程序,获取一个int变量num的地址,并显示在终端

                图片.png

                1.2.2 将num的地址赋值给指针ptr,并通过ptr去修改num的值

                图片.png

            1.3 指针细节说明

                a、值类型,都有对应的指针类型,形式为 *数据类型,比如int对应的指针类型就是 *int;*float32对应的指针类型就是 *float32;按此类推

                b、值类型包括:基本数据类型int系列、float系列、bool、string、数组和结构体struct

        2、值类型和引用类型

            2.1 常见的值类型和引用类型

                值类型:基本数据类型int系列、float系列、bool、string、数组和结构体struct

                引用类型:指针、slice切片、map、管道chan、接口interface等都是引用类型

            2.2 值类型和引用类型使用特点

                值类型:变量直接存储,内存通常在栈中(一般生命周期短的分配在栈区,但不绝对是,变量在别的函数用到,有可能放堆区,逃逸了)分配

                图片.png

                引用类型:变量存储的是一个地址,这个地址对应的空间才是真正存储的数据(值),内存通常在堆(一般生命周期长的分配在堆区,但不绝对是)上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由GC来回收

                图片.png

                内存栈区和堆区示意图:

                图片.png


        3、数组

            3.1 基本介绍

                数组可以存放多个同一类型数据,数组也是一种数据类型,在Go中,数组是值类型

            3.2 数组定义和访问数组元素

                方式一、

                var 数组名 [数组长度]数据类型

                var chicken [5]float64

                赋值:chicken[0] = 10  chicken[1] = 20

                方式二、

                变量名 := [数组长度]数据类型{元素值1,元素值2,...} 

                a := [3]int{10,20,30}

                其他方式::

                var chicken [3]int = [3]int{10,20,30}

                var chicken  = [3]int{10,20,30}

                var chicken  = [...]int{5,6,7}

                指定元素值对应下标

                var name = [3]string{1:"tom",2:"LeSeein",3:"yasuo"}

                image.png

                访问数组中元素:chicken[0]     chicken[2]  

                

            3.3 数组在内存的布局

                image.png

                说明:

                a、数组地址可以使用&  取地址获得

                b、数组的第一个元素的地址就是数组的首地址

                c、数组的各个元素的地址间隔是依据数据的类型决定的,比如int 64位系统占用8个字节

                案例演示:

                image.png

            3.4 数组遍历

                方式一:for循环遍历

                image.png

                方式二:for - range方式遍历

                image.png

                案例:

                image.png

            3.5 数组使用细节和注意事项

                a、数组是多个相同类型数据组合,一个数组一旦声明/定义了,其长度是固定的,不能动态变化

                image.png

                b、var  arr []int ,这时候arr是一个slice切片

                c、数组中的元素可以试任何数据类型,包括值类型和引用类型,但是不能混合使用

                d、数组在创建后没有赋值是有默认值的(零值),数值类型默认0 , 字符串类型默认空字符串,bool数组默认false

                image.png

                e、使用数组的步骤: 1.声明数组并开辟空间   2.给各个元素赋值  3.使用数组

                f、数组的下标是从0开始的

                g、数组下标必须在指定范围内使用,否则报panic:数组元素超出长度,比如var arr [3]int,则有效下标为[0-2]

                h、在Go中,数组属于值类型,在默认情况下是值传递,因此会进行值拷贝,数组间不会互相影响

                主函数:

                image.png

                test函数:

                image.png

                数组值拷贝内存详解:

                image.png

                i、如果在其他函数中想修改原来数组的值,可以使用引用传递(指针方式)

                image.png

                image.png                

                函数中修改数组值内存详解:

                image.png

                j、长度是数组类型的一部分,在传递函数参数时,需要考虑数组的长度

                image.png

            3.6 数组应用案例

                image.png

            3.7 多维数组

                3.7.1 二维数组介绍(这里只介绍二维数组)

                3.7.2 二维数组声明、赋值

                image.png

                image.png

                image.png

                image.png


                3.7.3 二维数组应用

                image.png

                3.7.4 二维数组在内存的形式

                image.png

        4、切片

            4.1 在go中为什么需要切片?

            假如我们需要一个数组来保存学生成绩,但是学生人数不确定的情况又该怎么办呢?  解决方案:使用切片!!! 

            4.2 切片的基本介绍

            a、切片的英文是slice

            b、切片是数组的一个引用,因此切片是引用类型,在进行传递时,遵守引用传递的机制

            c、切片的使用和数组类似,遍历切片、访问切片的元素和求切片的长度len(slice)都一样

            d、切片的长度是可以变化的,因此切片是一个可以动态变化的数组

            e、切片定义的基本语法

                var 切片变量名 []类型,比如:var num []int           

            image.png

            4.3 切片在内存中的形式

            image.png

            4.4 切片的使用

            方式一、定义一个切片,然后让切片去引用一个已经创建好的数组,

            image.png

            方式二、通过make来创建切片,基本语法:var 切片名 []type = make([],len,cap)

            说明:type:数据类型   len:大小      cap:指定切片容量,可选,如果分配了cap,则要求cap >= len

            image.png

            

            image.png

            内存布局:

            image.png

            以上两种方式轻易切片的区别:

            a、通过make方式创建的切片可以指定切片的大小和容量

            b、如果没有给切片的各个元素赋值,那么就会使用默认值[int、float=>0  string=>""   bool=>false]

            c、通过make方式创建的切片对应的数组是由make底层维护,对外不可见,即只能通过slice去访问各个元素


            方式三、定义一个切片,直接指定具体数组,使用原理类似make的方式

            image.png

            4.5 以上前两种方式的区别

            a、方式一时直接引用数组,这个数组是事先存在的,程序员是可见的

            b、方式二是通过make来创建切片,make也会创建一个数组,是由切片在底层进行维护,程序员是看不见的,make创建的切片示意图如下:

            image.png

            4.6 切片的遍历

            for循环遍历和for-range遍历

            image.png

            4.7 切片注意事项和细节说明

            a、切片初始化时,var slice = abc[startIndex : endIndex] ,从数组abc下标为 startIndex 开始, 取值到下标为endIndex元素,但不包括endIndex元素

            b、切片引用数组时,不能超过最大长度,范围在0~len(abc)之间,但是可以动态增加

                var slice = abc[0 : endIndex]  可以简写   var slice = abc[ :endIndex]

                var slice = abc[startIndex  : len(abc)]  可以简写   var slice = abc[ startIndex : ]

                var slice = abc[0: len(abc)]  可以简写   var slice = abc[ : ]

                image.png

            c、cap是一个内置函数,用于统计切片的容量,即最大可以存放多少个元素

            d、切片定义后还不能使用,因为本身是一个空的,需要让其引用到一个数组,或者make一个空间供切片使用

            e、切片可以继续切片

                image.png

                image.png

            e、append()内置函数可以对切片进行动态追加

                image.png

                切片append()操作的底层原理分析:

                1、切片append操作的本质是对数组扩容

                2、go底层会创建一个新的数组newArr(安装扩容后的大小,再重新赋值给新的切片)

                3、将slice原来包含的元素拷贝到新的数组newArr

                4、slice重新引用到newArr

                5、newArr是在底层来维护,程序员是看不见的

                image.png

                image.png

                image.png

            f、切片的拷贝操作,使用copy内置函数实现拷贝

                image.png

                说明:

                1、copy(param1,param2)参数类型必须都是切片

                2、param1,param2 两个切片空间独立,互不影响

            g、元素多的切片拷贝给元素少的切片,一样没问题

                image.png

            4.7 string和slice的使用

                4.7.1 string底层是一个byte数组,因此string也可以进行切片处理

                image.png

                4.7.2 string和切片在内存的形式示意图

                image.png

                4.7.3 string是不可变的,也就是说不能通过str[0] = ‘q’方式来修改字符串

                4.7.4 如果要修改string字符串中某一个字符的值,可以转切片修改,修改以后再转string

                image.png

            4.7 切片练习

                image.png


        5、排序和查找

            5.1 排序基本介绍

                排序是指将一组数据,依照指定的顺序进行排列的过程

                第一类:内部排序(数据量比较小)

                将需要处理的所有数据都加载到内部存储器中进行排序,包括(交换式排序法、选择式排序法和插入式排序法)

                image.png

                案例:

                image.png

                第二轮的第一次比较基于第一轮最后一次比较的结果之上进行,以后每次比较同理...

                image.png

                代码:

                image.png                


                第二类:外部排序(数据量比较大)

                数据量过大,无法全部加载到内存中,需要借助外部存储进行排序,包括(合并排序法和直接合并排序法)

            5.1 查找基本介绍

                image.png

                5.1.1 顺序查找

                image.png

                5.1.2 二分查找(前提:有序数列!!!)

                思路分析:

                image.png

                每次折半查找

                image.png

                案例演示:

                image.png

        6、map

            6.1 基本介绍

            map是key-value的数据结构,又称为字段或者关联数组,官方称之为映射,类似其他编程语言的集合

            6.2 基本语法

            var map 变量名     map[keytype]valuetype

            keytype可以是什么类型::golang中map,key的类型又很多,比如:bool,数字,string,指针,channel,还可以是只包含前面几个类型的接口、结构体、数组, 通常为有int、string

            注意:slice、map还有function不可以,因为这几个没法用==来判断

            valuetype可以是什么类型::基本跟keytype一样的,通常为数字(整数、浮点数)、字符串、map、struct

            

            image.png

            注意:map跟数组不一样,数组声明以后就已经分配内存空间地址了

            6.3 案例演示

            image.png   

            说明:

            map在使用前一定要先make;map的key不能重复,重复了就是最后一个key-value值;map的value值可以试相同的;map的key-value是无序的

            6.4 map的使用方式

             image.png

            案例:

            image.png

            6.5 map的增删改查操作

            a、添加和更新

            image.png

            b、删除

            image.png

            注意:如果我们要删除map的所有key,没有一个专门的方法一次删除,可以遍历一下key,逐个删除,或者map = make(...),make一个新的,让原来的称为垃圾,被gc回收

            image.png

            c、查询

            查询有两个返回参数   var,findRes = names["num1"]  var就是查找的key对应的value值,findRes查找结果(值为true 和 false)

            image.png

            image.png

            image.png

            6.6 map遍历,只能使用for-range结构遍历,map的key不一定都是数字

            image.png

            6.7 map的长度统计,使用len函数

            image.png

            image.png

            6.8 map切片

            基本介绍:

            切片的数据类型如果是map,则我们称之为slice of map,map切片,这样使用则map这个数就可以动态变化了

            image.png

            6.9 map排序

            基本介绍:

            a、golang中没有专门的方法针对map的key进行排序

            b、golang中map默认是无序的,注意,也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样

            c、golang中map的排序,是先将key排序,然后根据key值遍历输出即可

            image.png

            6.10 map使用细节说明

            a、map是引用类型,遵守引用类型传递机制,在一个函数接收map,修改后,会直接修改原来的值

            b、map容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说,map能动态的增加键值对

            c、map的value也经常使用struct类型,更适合管理一些复杂数据类型

            案例演示:

            image.png

            image.png

        7、管道channel

            7.1 基本介绍

            image.png

            image.png

            7.2 管道示意:

            image.png

            image.png

            image.png

            7.3 管道基本使用

            声明/定义channel:

            var 变量名  chan 数据类型   !!!


            var perChan chan *Person

            var intChan  chan int

            var mapChan chan map[int]string    (用于存放map[int]string类型数据)

            说明:

            1.channel是引用类型

            2.channel必须初始化才能写入数据,即make后才能使用

            3.channel是有类型的,intChan 只能写入int类型数据

            

            演示管道的使用:

            image.png

            image.png

            7.4 channel使用注意事项

            a、channel中只能存放指定的数据类型

            b、channel中数据放满了就不能再往里面存放数据了

            c、如果从channel中取出数据以后就可以继续存放

            d、在没有使用协程的情况下,如果channel数据取完了,再取,就会报dead lock


            7.5读写channel案例演示

            image.png

            image.png

            7.6 channel的遍历和关闭

            image.png

            image.png





        

            

            


            

            

            

            







【原创】 phpStorm编辑器使用
18 09 2021

phpStorm编辑器使用

        1、使用时间续期

            1.1、把ide-eval...拖至phpStorm编辑器编辑区域

            图片.png

            1.2、把ide-eval...拖至phpStorm编辑区,如下,点击restart

            图片.png

            1.3、点击Help,再点击Eval Restart

            图片.png

            1.4、点击Reset设置,勾选Auto reset ,再点击Reload加载刷新

            图片.png

            1.5、查看使用期限,完成设置

            图片.png


        2、去掉phpStorm编辑区的竖线

            2.1、按下Ctrl + Shift + A

            2.2、输入show right margin

            2.3、选择off

            图片.png

【原创】 Linux环境配置PHP-Redis扩展
15 09 2021

Linux环境下配置Redis扩展

        1、PHP7.2.33配置Redis扩展

            1.1 新建php-redis目录

            图片.png

            1.2 进到php-redis目录下载扩展

            wget https://pecl.php.net/get/redis-5.2.1.tgz

            图片.png

            1.3 解压

            tar -zxvf redis-5.2.1.tgz

            图片.png

            1.4 在解压目录下执行phpize,若是没有生成configure,则安装zutoconf,然后再执行phpize    

            图片.png

            1.5 编译安装

            ./configure --with-php-config=/www/server/php/72/bin/php-config  --enable-redis

            图片.png

            make && make install

            图片.png

            1.6 写入php.ini文件并重启

            图片.png

            

            图片.png

            然后重启PHP    systemctl restart php-fpm

            1.7 测试

            图片.png

            

            


【原创】 Linux环境下安装redis6.0.8
11 09 2021

Linux环境下安装redis

        1、安装Redis

            1.1 新建redis目录

            image.png

            1.2 下载redis6.0.8安装包

           wget http://download.redis.io/releases/redis-6.0.8.tar.gz

            image.png

            1.3 解压

            tar -zxvf redis-6.0.8.tar.gz

            图片.png


            图片.png

            1.4 安装C语言编译环境 

            查看和升级gcc版本(gcc版本过低需要升级,如果是高版本可以省略此步骤)

            图片.png

            更新命令如下:

            yum -y install centos-release-scl

            yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

            scl enable devtoolset-9 bash

            再次查看gcc版本:

            图片.png

            1.5 编译

            先进入到redis-6.0.8目录

            image.png

            make

            图片.png

            1.6 安装

            make install

            进入到redis-6.0.8目录下面的src目录执行

             图片.png

            也可以直接make && make install

            image.png


           图片.png

            查看默认安装位置

            图片.png

            1.7 测试,前台启动

            图片.png


            图片.png

            1.8 查看redis进程

            ps -ef|grep redis

            图片.png

            图片.png

            1.9 配置后台启动,快捷启动命令

            vim /root/software/redis-6.0.8/redis.conf

            注释bind127.0.0.1,否则只有本机才能访问

            图片.png

            

            图片.png

           修改 daemonize no 为daemonize yes 开启守护进程模式,设置为后台运行,进程不会终止,除非手动kill该进程

            图片.png

            设置外网可链接,protected-mode值改为no

            保护模式,该模式控制外部网是否可以连接redis服务,默认是yes,所以默认我们外网是无法访问的,如需外网连接rendis服务则需要将此属性改为no。

            图片.png

           

            设置redis密码,打开注释,后面设置自己的密码

            图片.png

            保存退出


            其他配置:

            监听端口:

            image.png

            日志、持久化文件保存目录:

            image.png

            数据库数量,设置为1代表只使用一个库,默认16个库,0~15

            image.png

            设置redis能够使用的最大内存

            image.png

            日志文件,默认为空,不记录日志,可以指定日志文件名

            image.png

            

            1.10 将redis设置成开机自启动(后台启动)

            a、首先创建几个目录

            图片.png

           b、将redis安装目录的redis.conf复制一份到/etc/redis目录下,命名为6379.conf

            c、修改6379.conf的logfile 为/var/log/redis/6379.log

             图片.png

            d、修改6379.conf的dir ./  为 dir /var/log/redis/data ,用来做redis持久化,保存后缀为.rdb的文件

            image.png

            e、将安装的redis目录下utils目录下的redis_init_script文件复制到/etc/init.d/下面,命名为redis

            f、修改/etc/init.d/redis文件

            图片.png

            图片.png

            

            g、将redis服务设置开机自启动  chkconfig  redis on

            图片.png

            h、重启reboot,  查看进程  ps -ef|grep redis

         

            1.11 本机登录redis

            auth 密码

            图片.png



            远程链接不上使用以下命令启动redis:redis-server /root/software/redis-6.0.8/redis.conf  

            

            1.12 redis的启动

            image.png

            1.13 redis客户端连接

            image.png



【原创】 第四章、Golang基本数据类型
03 09 2021

第四章、Go基本数据类型

  第一章、数据类型基本介绍

   图片.png


        图片.png

        1、整数类型

            1.1 基本介绍

                简单的说,就是用来存放整数值得,比如,0,-1,139等

            1.2 整数类型有哪些

                Go语言内置了12种整数类型,分别是 byte、int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、uintptr,其中byte是uint8的别名

                图片.png

                

                int8范围测试:

                图片.png


                图片.png

                uint8范围测试:

                图片.png


                图片.png

                byte范围测试:

                图片.png

            1.3 整型使用细节

                a、整型分为有符号和无符号类型,int、uint

                b、golang的整型默认声明为int类型

                图片.png

                c、如何在程序中查看某个变量的字节大小和数据类型

                图片.png

            

                图片.png 

                d、golang程序中整型变量在使用时,遵循保小不保大的原则,即:保证程序正确运行的情况下,尽量使用占用内存空间小的数据类型

                e、bit:计算机中最小存储单位,byte:计算机中基本存储单元

                图片.png

                  

        2、浮点类型

            2.1 基本介绍

                小数类型/浮点类型就是用于存放小数的

            2.2 小数类型分类

                图片.png

                说明:

                a、浮点数在机器中的存放形式,浮点数=符号位+指数位+尾数位; 浮点数都是有符号的

                b、尾数部分可能丢失,造成精度损失,  如:-123.0000906;float64精度比float32精度高 

                图片.png

                c、浮点数的存储分为三部分:符号位+指数位+尾数位,在存储过程中,精度会有损失

            2.3 浮点型使用细节

                a、golang浮点型有固定的范围和字段长度,不受具体OS影响。

                b、golang浮点型默认声明为float64类型

                c、浮点型常量有两种表现形式

                十进制形式:5.69        0.896 / .896

                科学计数法形式:5.1234e2 = 5.1234 * 10 的2次方;9.56E-2 = 9.56 / 10的2次方

                d、通常情况使用float64,因为它比float32更精确

        3、字符类型(char)

            3.1 基本介绍

                golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来存。字符串就是一串固定长度的字符链接起来的字符序列,go字符串是由单个字节连接起来的;也就是说对于传统的字符串是由字符组成的,而go的字符串不同,它是由字节组成的!!!

                 Go内置两种字符类型:一种是byte的字节类类型(byte是uint8的别名),另一种是表示Unicode编码的字符rune,rune在Go内部是int32类型的别名,占用4个字节,Go语言默认的字符编码就是UTF-8,如果需要特殊的编码转换,则使用unicode/UTF-8标准包


            3.2 字符类型的使用

                图片.png


                图片.png


                图片.png

                说明:

                a、如果我们保存的字符在ASCII表内,如[0-9a-zA-Z],可以直接保存到byte

                b、如果我们保存的字符对应码值大于255,这时可以考虑使用int类型保存

                c、如果我们需要按照字符的方式输出,这时需要格式化输出,即:fmt.Printf(“c5=%c”,c5)

            3.3 字符类型使用细节

                a、字符常量是使用  单引号''  括起来的单个字符,列如:var byte c1 = 'a' ; var byte c2 = '9'; var int c3='中'

                b、go中允许使用转义字符‘\’来将其后的字符转义为特殊字符型常量。   列如:var c3 char = '\n'     // '\n'表示换行符

                c、go语言的字符使用UTF-8编码    UTF-8编码兼容ASCII码,在UTF-8编码中英文占用1个字节,汉字占用3个字节

                d、在go中,字符的本质是一个整数,直接输出时,是该字符对应UTF-8编码的码值

                e、可以直接给某一个变量赋一个数字,然后按格式化输出时%c,会输出该数字对应的unicode字符

                图片.png

                f、字符类型是可以进行运算的,相当于一个整数因为它都对应又unicode码

                图片.png

                g、字符类型使用单引号 '' 把字符括起来

                golang按照unicode编码进行处理的,UTF-8是unicode码的具体实现

            3.4 字符类型本质探讨

                a、字符型存储到计算机中,需要将字符对应的码值(整数)找出来

                存储:字符 --> 转对应码值 --> 码值转二进制 --> 存储

                读取:二进制 --> 转对应码值 --> 找出字符 --> 读取 

                b、字符和码值的对应关系是通过字符编码表决定的(是规定好的)

                c、go语言的编码都同一成了utf-8,非常方便,再也没有编码乱码的困扰了

        4、布尔类型

            4.1 基本介绍

                布尔类型也叫bool类型,bool类型数据只允许取值true和false;布尔类型占用内存空间1个字节;bool类型多用于逻辑运算,一般用于程序流程控制(if流程控制语句、for循环控制语句)。

        5、字符串类型

            5.1 基本介绍

                字符串就是一串固定长度的字符链接起来的字符序列,go的字符串是单个字节连接起来的,go语言的字符串的字节使用UTF-8编码标识Unicode文本

            5.2 字符串的使用

                图片.png

            5.3 字符串使用细节

                a、go语言的字符串的字节使用UTF-8编码标识Unicode文本,golang统一使用UTF-8编码,中文乱码问题不会再困扰程序员

                b、字符串一旦赋值了就不能直接修改每一个元素,只能通过重新构造新的字符串并赋值给原来的字符串变量实现,在go中字符串是不可变的

                图片.png

                c、字符串的两种表示形式

                    1、双引号,会识别转义字符

                    图片.png

                    2、反引号,以字符串原生的形式输出,包括换行和特殊字符,可以实现防止攻击,输出源代码等效果

                    图片.png

                d、字符串拼接方式

                    图片.png

                e、当一行字符串太长时,需要使用到多行字符串,可以如下处理

                    图片.png

            5.4 字符串的常用操作

                image.png


        6、基本数据类型默认值(零值)

            6.1 基本介绍

                golang中,数据类型都有一个默认值,当程序员没有赋值时,就会使用默认值,在go中默认值也叫零值

            6.2 基本数据类型的默认零值如下:

                    图片.png

            6.3 演示基本数据类型输出默认值

                图片.png


        7、基本数据类型的转换

            7.1 基本介绍

                golang和java/c不同,go在不同类型的变量之间赋值需要显式转换(强制转换),也就是说golang中数据类型不能自动转换

            7.2 基本语法

                表达式T(v),将值v转换为类型T

                T就是数据类型,如:int32,int64,float64等等

                v就是需要转换的变量

            7.3 基本数据类型转换的案列

                图片.png

            7.4 基本数据类型转换的使用细节

                a、go中,数据类型的转换可以使范围小的 --> 范围大的; 也可以是范围大的 --> 范围小的

                b、被转换的是“变量存储的数据”(即值),变量本身的数据类型没有发生改变!

                c、在转换中,比如将int64转换为int8【-128 ~ +127】,编译时不会报错,只是转换结果按溢出处理,和我们希望的不一样。

                图片.png

                练习1:

                图片.png

                练习2:

                图片.png

                

                图片.png

            7.5 基本数据类型和string的转换

                7.5.1 基本数据类型转string

                    基本介绍:

                    在程序开发中,我们经常将基本数据类型转string,或者将string转基本数据类型

                    方式一:fmt.Sprintf("%参数",表达式)

                    函数介绍:

                    图片.png

                    案列演示:

                    图片.png

                    方式二:使用strconv包的函数

                    函数介绍:

                    图片.png

                

                    图片.png

                    案列演示:

                     图片.png

                    方式三:使用strconv.Itoa函数

                    图片.png


                7.5.2 string类型转基本类型

                    方式一:使用strconv包的函数

                    图片.png

                    案列演示:

                    图片.png

            7.6 注意事项

                在将string数据类型转换为基本数据类型时,要确保string类型能够转成有效的数据,比如:我们可以把“123”转成一个整数,不能把“hello”转成一个整数,如果强制转换,golang直接将其转为0,其它的一样的道理,float --> 0; bool --> false

                    图片.png




  

                

【原创】 第三章、Go语言基础知识
19 08 2021

第三章、Go语言基础语法

  第一、Golang概述

        1、Go语言结构

            1.1 Go语言的基础组成部分:

                包声明、引入包、函数、变量、语句&表达式、注释

        2、Go语言开发注意事项

                a、Go源文件以"go"为扩展名

                b、Go应用程序的执行入口是main()函数

                c、Go语言严格区分大小写

                d、Go方法有一条条语句构成,每个语句不需要加分号(Go语言会在每行后自动加分号)

                e、Go编译器是一行行进行编译的,因此我们一行就写一条语句,不能把多条语句写在同一行,否则报错

                f、Go语言定义的变量或者引用的包如果没有使用到,代码不能编译通过

                g、大括号成对出现,缺一不可

                h、源程序默认UTF-8编码

                i、定义函数以func开头,函数体开头的"{"不能换行

        3、Go语言转义字符(Escape character)

                a、\t :一个制表符,实现对齐的功能

                b、\n :换行符

                c、\\ :一个\

                d、\" :一个"

                e、\r :一个回车,fmt.Println("天龙八部雪山飞狐\r张飞")

                图片.png


        4、Go语言代码风格

            4.1 Go官方推荐使用行注释来注释整个方法和语句

            4.2 运算符两边习惯性各加一个空格,比如:2 + 3 * 5

            4.3 方法体后面的“{”不能换行,如下:

                图片.png

        5、Golang官方编程指南

            5.1 官方网站:https://golang.org

            5.2 Go语言中文文档:https://studygolang.com/pkgdoc

            5.3 Golang的包和源文件和函数的关系简图

                图片.png

            Golang中调用一个函数的方式:import引入包名, 再使用包名.函数的方式调用函数


        知识回顾

            1、Go语言的SDK是什么?

            SDK就是软件开发工具包

            2、Golang环境变量配置及其作用

            GOROOT:指定go sdk安装目录;GOPATH:golang的工作目录,我们项目的源码都放在GOPATH指定的目录下

            3、Golang程序的编写、编译、运行步骤是什么?

            编写:就是编写源码

            编译:go build 源码  -> 生成一个可执行文件

            运行:1.对可执行文件运行  xx.exe      2.go run 源码

            4、Golang程序的编写规则

                4.1 go文件后缀以.go结尾

                4.2 go程序区分大小写

                4.3 go语句后不需要带分号";"

                4.4 go定义的变量或者import包必须使用,如果没有使用就会报错

                4.5 go中不要把多条语句放在同一行,否则报错

                4.6 go中的大括号风格如下,不能换行

                图片.png

           

  第二、Golang变量

        1、Golang变量

            变量:使用一个名称来绑定一个内存地址,该内存地址中存放的数据类型由定义变量时指定的类型决定,该内存地址里面存放的内容可以改变。

            局部变量:在函数或方法内部定义使用的变量

            全局变量:在函数外部定义的变量

            变量定义了必须使用,不然编译会出错,但是全局变量定义了不使用是不会报错的

            变量三要素:变量名、值、数据类型


            1.1 变量使用步骤

                先声明变量、再给变量赋值、再使用变量

            1.2 变量使用的三种方式

                注意: 使用:=定义变量(:=方式只能在函数内部使用,并且左边的变量不应该是已经声明过的),此类声明变量的方式为短类型声明

                图片.png

            1.3 多变量声明

                图片.png

            1.4 声明全局变量(在函数外部声明的变量就是全局变量)

                图片.png

            1.5 变量使用注意事项

                1.5.1 变量在某区域数据值可以在同一类型范围内不断变化

                图片.png

                1.5.2 变量在同一作用域(在同一个函数或者代码块内)不能重名

                图片.png

                1.5.3 变量三要素:变量名、变量类型、变量值

                1.5.4 Golang的变量如果没有赋初值,编译器会使用默认值,比如:int默认值0,string默认值为空串,小数默认为0,               

                1.5.5 声明变量、初始化变量、给变量赋值操作

                声明变量:var i int      var num float32

                初始化变量:var a int = 50   var b = 400

                给变量赋值:比如先声明了变量var m int ,然后再给值   m = 100,这就是给变量赋值

            1.6 匿名变量

            image.png



        2、程序中+号的使用

            2.1 当+号左右两边都是数值类型时候,则做加法运算

            2.2 当+号左右两边都是字符串时候,则做字符串拼接

            图片.png

  第三、Golang常量

        1、Golang常量简介

                常量:使用一个名称来绑定一个内存地址,该内存地址里面存放的内容不可以改变,Go中常量分为布尔型、字符串型、数值型(整数型、浮点型和复数),使用const关键字定义常量

            1.1 常量基本介绍

                常量的定义格式:

                const identifier [type] = value   你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。

                const b string = "abc"                    //显式类型定义

                const a,c = "abc","bcd"                  //隐式类型定义  

                常量还可以用作枚举:

                const(

                    Unhnow = 0        //性别未知

                    Female = 1          //女性 

                    Male = 2             //男性

                )

                常量可以用len(), cap(), unsafe.Sizeof()常量计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:

                iota,特殊常量,可以认为是一个可以被编译器修改的常量。

                在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。

                iota 可以被用作枚举值:

                图片.png

                第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2   

                可以简写为如下形式:

                 图片.png 

                image.png

                注意细节:

                细节1:

                image.png

                image.png

                细节2:

                image.png

                image.png

                细节3:

                image.png

                image.png

                细节4:

                image.png

                image.png

                细节5:

                image.png

                image.png

                细节6:

                image.png

                image.png


                总结::

                iota,特殊常量,可以认为是一个可以被编译器修改的常量;在每一个const关键字出现时,被重置为0;然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1; “const声明中,每新增一行代码行常量声明iota计数一次“;细节4中某一行声明了没有赋值,默认和上一行一致;一行中出现多个iota,当前行的iota只加1

                案例演示:

                图片.png

                第一行:1左移0位=1; 第二行:1左移10位 = 2的十次方  = 1024;...


  第四、复数类型

        1、复数类型基本介绍

            Go语言两种复数类型,分别是complex64、complex128,复数在计算机里面使用两个浮点数表示,一个表示实部一个表示虚部。complex64是由两个float32构成,complex128是由两个float64构成,复数的字面量表示和数学表示法一样

            complex64    32位实数和虚数  (复数)

            complex128    64位实数和虚数 (复数)

            图片.png

  第五、Go词法单元

            1.3.1 token

                token是构成源程序的基本不可分割的单元,编译器编译程序的第一步就是将源程序分割为一个独立的token,这个过程叫词法分析,Go语言的token可分为关键字、标识符、操作符、分隔符和字面常量等。

                Go的token分隔符有两类,一类是操作符还有一种自身没有特殊含义仅用来分隔其他token,被称为纯分隔符。

                sum := a+b   “:=”“+”既是分隔符也是token,所以这个简单的语句被分为5个token: "sum"、“:=”、“+”、“a”、“b”

                纯分隔符:空格、制表符、换行符、回车符,多个相邻的空格或制表符会被编译器看做分隔符处理。

                    图片.png



 






【原创】 单工通信与双工通信
16 06 2021

单工通信与双工通信

        1、基本概念

            全双工:通信允许数据在两个方向同时传输,它在能力上相当于两个单工通信的结合。双工通信可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指A→B的同时B→A,是瞬时同步的。

            单工:只允许A→B传送信息,B是不能向A发送信息。


【原创】 Mysql锁机制
09 06 2021

Mysql锁机制

一、Mysql是一个单进程多线程架构数据库

        1、Mysql锁概述

            相对于其他数据库而言,Mysql的锁机制比较简单,最显著的特点就是不同的存储引擎支持不同的锁机制。比如,MyISAM和MEMORY存储引擎采用的是表级锁,BDB存储引擎采用的是页面锁,但也支持表级锁,InnoDB存储引擎既支持表级锁,也支持行级锁,默认情况下采用的行级锁。

        2、Mysql这三种锁的特性大致归纳如下:开销、加锁速度、死锁、粒度、并发性能

            表级锁(锁定整个表):开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。注意:字段索引值,表级锁中字段没有索引,如果使用该字段作为操作条件会造成整张表锁定。

            行级锁(锁定某个id记录):开销大,加锁慢;会出现死锁;锁定粒度最小,发生冲突的概率最低,并发度也最高。

            页面所:开销和加锁时间介于表级锁和行级锁之间;会出现死锁;锁定粒度介于表级锁和行级锁之间,并发度一般。

            仅从锁的角度来说,表级锁更适合于查询为主,只有少量按索引条件更新数据的应用,如web应用;而行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理系统。

            从上述很难笼统的说哪种锁更好,只能就具体的应用特点来说哪种锁更适合。

            

            Mysql的表级锁有两种模式:表共享读锁(Table Read Lock) 和 表度占写锁(Table Write Lock),一般用于MyISAM存储引擎

            给表加锁:

            1. 表共享读锁,其他用户只能读取,不能添加、更改

            lock table 表名 read

            2. 表独占写锁,其他用户不能读取,也不能添加、更改

            lock table 表名 write


            Mysql的innoDB存储引擎一般使用悲观锁和乐观锁:

            悲观锁(文件锁、行锁):假设当前操作一定会发生冲突,屏蔽一切,阻塞、等待状态,适用于访问量少的场合,不能用于访问量大,并发高的场合,“速度慢,性能差”


            说明:

            1. 对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对MyISAM表的写操作,会阻塞其他用户对同一表的读写操作,MyISAM表的读操作于写操作之间,以及写操作之间是串行的!当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程读、写操作都会等待,直到锁被释放为止。

            2. 一个session使用LOCK TABLE命令给表f加了读锁,这个session可以查询锁定表中记录,但更新或者访问其他表都会提示错误;同时,另一个session可以查询f表的记录,但更新就会出现锁等待。

        3、并发插入




【原创】 笔记一、HTTP协议
07 06 2021

一、HTTP概述

        1、什么是HTTP?

            HTTP:超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。

        2、初识浏览器控制台

            2.1、Network网络

            2.1.1、消息头headers

            General:普通的、常规的

                 Request Url:请求地址

                 Request Method:请求方式

                 Status Code:状态码

                 Remote Address:远程地址

                 Referrer Policy:Referrer(来路、来源网址)

                 Referrer作用:referrer是用于追踪用户是从哪个页面跳转过来,设置为no-referrer,表示所有请求都不发送referrer.
如果content属性不是合法的取值,浏览器会自动选择no-referer策略

                 Referrer取值:

                     No Referrer:任何情况下都不发送referrer信息

                    No Referrer When Downgrade:仅当发生协议降级(如 HTTPS 页面引入 HTTP 资源,从 HTTPS 页面跳到 HTTP 等)时不发送 Referrer 信息。这个规则是现在大部分浏览器默认所采用的;

                    Origin Only:发送只包含 host 部分的 Referrer。启用这个规则,无论是否发生协议降级,无论是本站链接还是站外链接,都会发送 Referrer 信息,但是只包含协议 + host 部分(不包含具体的路径及参数等信息);

                    Origin When Cross-origin:仅在发生跨域访问时发送只包含 host 的 Referrer,同域下还是完整的。它与 Origin Only 的区别是多判断了是否 Cross-origin。需要注意的是协议、域名和端口都一致,才会被浏览器认为是同域;

                    Unsafe URL:无论是否发生协议降级,无论是本站链接还是站外链接,统统都发送 Referrer 信息。正如其名,这是最宽松而最不安全的策略;



           Request UR Request URL:

            Request URL:

            Request URL

【原创】 mysql数据库设计三范式
25 05 2021

Mysql - 数据库设计三范式

    1、第一范式

    要求任何一张表必须有主键,每一个字段原子性不可再分

    image.png

    2、第二范式

    建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不要产生部分依赖

    ①

    image.png

    ② 

    image.png

    关系表设置外键,外键的关系字段分别为两张表的主键字段

    3、第三范式

    建立在第二范式的基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖

    ①

    image.png

    ②

    image.png


    总结如下:

    image.png

           


【原创】 Dos的常用指令
23 04 2021

DOS常用指令

        1、dos的基本介绍

            Dos: Disk Operating System 磁盘操作系统,  简单说一下 windows 的目录结构

        2、dos的基本操作原理

            用户:通过命令行窗口使用指令去操作Dos系统,Dos系统:解析用户输入指令,执行操作

            图片.png


        3、目录操作指令

            3.1查看当前目录操作   dir

            图片.png

            3.2切换到其他盘符  e:  或者 cd /d e:

            图片.png

            

            图片.png

            3.3切换到当前盘的其他目录

            图片.png

            3.4切换到上一级目录

            图片.png

            3.5切换到根目录

            图片.png

            3.6新建目录

            图片.png

            3.7删除目录

                3.7.1删除空目录

                图片.png

                3.7.2删除目录下面的文件和目录,不带询问

                图片.png

                3.7.3删除目录下面的文件和目录,带询问

                图片.png


        4、文件操作指令

            4.1新建或追歼内容到文件

            图片.png

            

            图片.png

            4.2复制

            图片.png

            4.3移动文件

            图片.png

            4.4删除文件

            图片.png

            

            图片.png

        5、其他指令

            5.1清屏:cls

            5.2退出dos:exit

            5.3查看被占用的端口:netstat -ano|findstr  端口号

            image.png

            5.4查看指定的PID:qprocess 端口号

            image.png


            


            


【原创】 杂七杂八
22 03 2021

一、工作中杂七杂八笔记

        1、TP5.1具体版本框架下载

        composer create-project topthink/think=5.1.41 TP51 

        

        2、Linux系统安装PHP压力测试工具安装

  • yum -y install httpd-tools    在linux系统执行前面代码, apache自带ab工具 nginx需要自己去安装

        ab  -n  xxx   -c  xxx     url

        image.png

        -n  requests(请求数,发送了多次请求):Number of requests to perform         要执行的请求数

        -c  concurrency(并发数,同时执行某一操作的人数):Number of multiple requests to make at a time   一次发出的多个请求

        注意:-c(并发数) 不能大于 -n(请求数)

        -c  concurre

        Server Software:        nginx/1.10.2 (服务器软件名称及版本信息)
        Server Hostname:        192.168.1.106(服务器主机名)
        Server Port:            80 (服务器端口)
        Document Path:          /index1.html. (供测试的URL路径)
        Document Length:        3721 bytes (供测试的URL返回的文档大小)
        Concurrency Level:      1000 (并发数)
        Time taken for tests:   2.327 seconds (压力测试消耗的总时间)
        Complete requests:      5000 (的总次数)
        Failed requests:        688 (失败的请求数)
        Write errors:           0 (网络连接写入错误数)
        Total transferred:      17402975 bytes (传输的总数据量)
        HTML transferred:       16275725 bytes (HTML文档的总数据量)
        Requests per second:    2148.98 [#/sec] (mean) (平均每秒的请求数) 这个是非常重要的参数数值,服务器的吞吐量,可以通过这个数据可以更好的了解到机器、程序性能情况 
        Time per request:       465.338 [ms] (mean) (所有并发用户(这里是1000)都请求一次的平均时间)
        Time  request:       0.247 [ms] (mean, across all concurrent requests) (单个用户请求一次的平均时间)
        Transfer rate:          7304.41 [Kbytes/sec] received 每秒获取的数据长度 (传输速率,单位:KB/s)

        注意:测试机要与被测试机分开;不要对线上的服务器做压力测试;观察测试工具缩在机器以及被测试机器的CPU、内存、网络,不超过最高限度的75%;写完一个接口尽量用压测工具去测试性能 !!!

        

        3、linux环境查看php安装的扩展

        php -m

        4、redis秒杀

        4.1 首先来看看现在存在的问题

        



            

 

            




【原创】 第二章、在各系统中安装Go
20 03 2021

第二章、Go安装

        1、windows平台下载Go安装包

            https://studygolang.com/dl

        1.1 安装

          图片.png



            图片.png

            

            图片.png


            图片.png


            图片.png


            图片.png


            

                图片.png            

            

            图片.png


            查看go版本 

             图片.png

        1.2 配置环境变量

            图片.png

            开启go mod模式:

            go env -w GO111MODULE=on

            设置国内代理:

            go env -w GOPROXY=https://goproxy.cn,direct

            图片.png


            Administrator的用户变量:只针对这个用户;系统变量:针对所有的用户变量都生效


图片.png

            

            查看环境

            图片.png


        2、Go语言命令行工具介绍

            go build:用于编译源码文件、代码包、依赖包

            go run:可以编译并运行Go源码文件

            go get:命令主要是用来动态获取远程代码包

        3、在linux平台下安装Go

            3.1 下载安装包

                https://studygolang.com/dl

                wget https://studygolang.com/dl/golang/go1.16.2.linux-amd64.tar.gz

                cd /usr/local/

            3.2 解压:

                tar -zxvf go1.16.2.linux-amd64.tar.gz

                图片.png

            3.3 配置环境变量

                配置环境变量:

                vi /etc/profile

                export GOROOT=/usr/local/go
                export GOPATH=/home/go
                export PATH=$PATH:$GOROOT/bin:$GOPATH/bin


                图片.png

            3.4 查看go版本和环境变量

                go version

                图片.png

               go env

                图片.png


        4、在linux中创建第一个go程序

            4.1.1 创建工作目录,建议在/home/go目录,  并且创建三个目录:bin(编译后的可执行文件的存放路径)  pkg(编译包时,生成的.a文件的存放路径)  src(源码路径,我们的工程一般创建在src目录下面)

            4.1.2 创建测试文件

            图片.png

            4.1.3 构建工程

            图片.png

            4.1.4 命令行直接输入编译文件的文件名

            图片.png


        5、编译

            image.png


        6、交叉编译

            image.png

            image.png

            

 

             

            


【原创】 第一章、初识Go语言
19 03 2021

第一章、Go语言简介

一、初识Go语言

        1、简介

                Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言

              罗伯特·格瑞史莫(Robert Griesemer),罗勃·派克(Rob Pike)及肯·汤普逊(Ken Thompson)于2007年9月开始设计Go,稍后Ian Lance Taylor、Russ Cox加入项目。Go是基于Inferno操作系统所开发的。Go于2009年11月正式宣布推出,成为开放源代码项目,并在LinuxMac OS X平台上进行了实现,后来追加了Windows系统下的实现。

        2.描述

                Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。Go的并行模型是以东尼·霍尔通信顺序进程(CSP)为基础,采取类似模型的其他语言包括OccamLimbo,但它也具有Pi运算的特征,比如通道传输。在1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。

与C++相比,Go并不包括如枚举异常处理继承泛型断言虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。Go 2.0版本将支持泛型,对于断言的存在,则持负面态度,同时也为自己不提供类型继承来辩护。

不同于Java,Go内嵌了关联数组(也称为哈希表(Hashes)或字典(Dictionaries)),就像字符串类型一样。
        3.撰写风格        

                在Go中有几项规定,当不匹配以下规定时编译将会产生错误。

        a、每行程序结束后不需要撰写分号(;)。

        b、大括号({)不能够换行放置。

        c、if判断式和for循环不需要以小括号包覆起来。

Go亦有内置gofmt工具,能够自动整理代码多余的空白、变量名称对齐、并将对齐空格转换成Tab。

        4.编译器

                当前有两个Go编译器分支,分别为官方编译器gc和gccgo。官方编译器在初期使用C写成,后用Go重写从而实现自举。Gccgo是一个使用标准GCC作为后端的Go编译器。

官方编译器支持跨平台编译(但不支持CGO),允许将源代码编译为可在目标系统、架构上执行的二进制文件。

        5.Go语言能做什么

                服务器编程,以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。

                分布式系统、数据库代理器、中间件等,例如Etcd。

                网络编程,这一块目前应用最广,包括Web应用、API应用、下载应用,而且Go内置的net/http包基本上把我们平常用到的网络功能都实现了。

        6.解释型语言与编译型语言的区别

                编译型语言已经提前编译成二进制代码了,执行效率更高

            image.png

        7.Go项目结构

            个人开发:

            image.png

            image.png


            企业开发:

            image.png




【原创】 PHP问题积累
18 03 2021

6.你们公司是使用什么框架?

答:我们公司采用的是 TP 框架,运用的 mysql+apache+php 进行开发,因为 TP 框架是一个免费开源的,轻量级的 php 开发框架,而且是我们中国人自己开发的,也是国内用的比较多的,各种资料也比较齐全

7.mvc 是什么?相互间有什么关系?

答:mvc 是一种开发模式,主要分为三部分:m(model),也就是模型,负责数据的操作;v(view),也就是视图,负责前后台的显示;c(controller),也就是控制器,负责业务逻辑

客户端请求项目的控制器,如果执行过程中需要用到数据,控制器就会到模型中获取数据,再将获取到的数据通过视图显示出来

8.OOP是什么?

答:oop 是面向对象编程,面向对象编程是一种计算机编程架构,OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。

OOP 具有三大特点

1、封装性:也称为信息隐藏,就是将一个类的使用和实现分开,只保留部分接口和方法与外部联系,或者说只公开了一些供开发人员使用的方法。于是开发人员只 需要关注这个类如何使用,而不用去关心其具体的实现过程,这样就能实现 MVC 分工合作,也能有效避免程序间相互依赖,实现代码模块间松藕合。

2、继承性:就是子类自动继承其父级类中的属性和方法,并可以添加新的属性和方法或者对部分属性和方法进行重写。继承增加了代码的可重用性。PHP 只支持单继承,也就是说一个子类只能有一个父类。

3、多态性:子类继承了来自父级类中的属性和方法,并对其中部分方法进行重写。于是多个子类中虽然都具有同一个方法,但是这些子类实例化的对象调用这些相同的方法后却可以获得完全不同的结果,这种技术就是多态性。多态性增强了软件的灵活性,具体表现在:

3.1 易维护:采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。

3.2 质量高:在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。

3.3 效率高:在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。

3.4易扩展:由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。

9.smarty 是什么,有什么作用?

答:回答一:smarty 是用 php 写出来的模板引擎,也是目前业界最著名的 php 模板引擎之一它分离了逻辑代码和外在的显示,提供了一种易于管理和使用的方法,用来将混杂的 php 逻辑代码与 html 代码进行分离

回答二:smarty 是 php 中最著名的引擎框架之一,我们公司使用的是 TP 框架,已经封装好了 smarty 模板,所以没有单独使用过

回答三:smarty 是个模板引擎,最显著的地方就是有可以把模板缓存起来。一般模板来说,都是做一个静态页面,然后在里面把一些动态的部分用一切分隔符切开,然后在 PHP 里打开这个模板文件,把分隔符里面的值替换掉,然后输出来,你可以看下 PHPLib 里面的template 部分。

而 smarty 设定了缓存参数以后,第一次运行时候会把模板打开,在 php 替换里面值的时候把读取的 html 和 php 部分重新生成一个临时的 php 文件,这样就省去了每次打开都重新读取 html 了。如果修改了模板,只要重新刷下就行了。

10.TP 框架有哪些优点?

答:TP 框架是我们中国人自己开发的框架,各种资料比较齐全,国内用的比较多,比较简单和方便,而且是免费开源的

11.TP 的特性有哪些?

答:

  1. 多表查询非常方便,在 model 中几句代码就可以完成对多表的关联操作
  2. 融合了 smarty 模板,使前后台分离
  3. 命名规范,模型,视图,控制器严格遵循命名规则,通过命名一一对应
  4. 命名规范,模型,视图,控制器严格遵循命名规则,通过命名一一对应
  5. 支持多种 url 模式
  6. 内置 ajax 返回方法,包括 xml,json,html 等
  7. 支持应用扩展,类库扩展,驱动扩展等

12.TP 框架中的大字母函数?

答:U:对 url 的组装
A:内部实例化控制器
S:缓存处理
R:调用某个控制器的操作方法
D:实例化自定义模型类
M:实例化基础模型类
I:获取参数
L:设置或者获取当前语言
C:设置或获取,保存配置

13.请介绍一下 laravel 框架?

答:laravel 框架的设计思想比较先进,非常适合应用各种开发模式,作为一个框架,它为你准备好了一切,composer 是 php 的未来。

laravel 框架最大的特点和优秀之处就是集合了 php 比较新的特点,以及各种各样的设计模式,Ioc 模式,依赖注入等

14.laravel 有那些特点?

答:回答一:

  1. 强大的 rest router:用简单的回调函数就可以调用,快速绑定 controller 和 router
  2. artisan:命令行工具,很多手动的工作都自动化
  3. 可继承的模板,简化 view 的开发和管理
  4. blade 模板:渲染速度更快
  5. ORM 操作数据
  6. migration:管理数据库和版本控制
  7. 测试功能也很强大
  8. composer 也是亮点

回答二:laravel 框架引入了门面,依赖注入,Ioc 模式,以及各种各样的设计模式等

15.请简述一下数据库的优化?

答:数据库的优化可以从四个方面来优化:

  1. 从结构层: web 服务器采用负载均衡服务器,mysql 服务器采用主从复制,读写分离
  2. 从储存层: 采用合适的存储引擎,采用三范式
  3. 从设计层: 采用分区分表,索引,表字段合适的字段属性,适当采用逆范式,开启 mysql 缓存
  4. sql 语句层:结果一样的情况下,采用效率高,速度快节省资源的 sql 语句执行

16.如何解决异常处理?

答: 抛出异常:使用 try...catch,异常的代码放在 try 代码块内,如果没有触发异常,则代码继续执行,如果异常被触发,就会抛出一个异常。Catch 代码块捕获异常,并创建一个包含异常信息的对象。$e->getMessage(),输出异常的错误信息。

解决异常:使用 set_error_handler 函数获取异常(也可以使用 try()和 catch()函数),然后使用 set_exception_handler()函数设置默认的异常处理程序,register_shutdown_function()函数来执行,执行机制是,php 要把调入的函数调入到内存,当页面所有的 php 语句都执行完成时,再调用此函数

17.前端

答:我在工作中处理前端的功能,一般就是用 ajax 向后台请求数据,然后返回数据在前台页面中显示出来。我从来没有独立的完整的将 html 和 css 样式都一个人完成,如果公司实在有这样的需求的话,我可能会找一些前台的模板或者说是前端的框架,比如说 h—ui 等等

18.权限管理(RBAC)的实现?

答:

  1. 首先创建一张用户表:id name auto(保存格式为:控制器-方法)
  2. 然后在后台中创建一个基类控制器,控制器里封装一个构造方法,当用户登陆成功后,使用 TP 框架中封装好的 session 函数获取保存在服务器中的 session id,然后实例化模型,通过用户 id 获取保存在数据表中的 auth 数据,使用 explode 函数分割获取到的数据,并使用一个数组保存起来,然后使用 TP 框架中封装好的常量获取当前控制器和方法,然后把他们组装成字符串,使用 in_array 函数进行判断该数组中是否含有当前获取到的控制器和方法,如果没有,就提示该用户没有权限,如果有就进行下一步操作

19.支付功能的实现?

答:

20.怎么保证促销商品不会超卖

答:这个问题是我们当时开发时遇到的一个难点,超卖的原因主要是下的订单的数目和我们要促销的商品的数目不一致导致的,每次总是订单的数比我们的促销商品的数目要多,当时我们的小组讨论了好久,给出了好几个方案来实现:

第一种方案是:①在每次下订单前我们判断促销商品的数量够不够,不够不允许下订单,更改库存量时加上一个条件,只更改商品库存大于 0 的商品的库存,当时我们使用 ab 进行压力测试,当并发超过 500,访问量超过 2000 时,还是会出现超卖现象。所以被我们否定了。

第二种方案是:②使用 mysql 的事务加排他锁来解决,首先我们选择数据库的存储引擎为 innoDB,使用的是排他锁实现的,刚开始的时候我们测试了下共享锁,发现还是会出现超卖的现象。有个问题是,当我们进行高并发测试时,对数据库的性能影响很大,导致数据库的压力很大,最终也被我们否定了。

第三种方案是:③使用文件锁实现。当用户抢到一件促销商品后先触发文件锁,防止其他用户进入,该用户抢到促销品后再解开文件锁,放其他用户进行操作。这样可以解决超卖的问题,但是会导致文件得 I/O 开销很大。

最后我们使用了 redis 的队列来实现。将要促销的商品数量以队列的方式存入 redis 中,每当用户抢到一件促销商品则从队列中删除一个数据,确保商品不会超卖。这个操作起来很方便,而且效率极高,最终我们采取这种方式来实现

21.商城秒杀的实现

答:抢购、秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个:

  1. 高并发对数据库产生的压力
  2. 竞争状态下如何解决库存的正确减少(”超卖”问题)

对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用 Redis。

第二个问题,我们可以使用 redis 队列来完成,把要秒杀的商品放入到队列中,因为 pop 操作是原子的,即使有很多用户同时到达,也是依次执行,文件锁和事务在高并发下性能下降很快,当然还要考虑其他方面的东西,比如抢购页面做成静态的,通过 ajax 调用接口,其中也可能会出现一个用户抢多次的情况,这时候需要再加上一个排队队列和抢购结果队列及库存队列。高并发情况下,将用户进入排队队列,用一个线程循环处理从排队队列取出一个用户,判断用户是否已在抢购结果队列,如果在,则已抢购,否则未抢购,库存减 1,写数据库,将用户入结果队列。

22.购物车的原理

答:购物车相当于现实中超市的购物车,不同的是一个是实体车,一个是虚拟车而已。用户可以在购物网站的不同页面之间跳转,以选购自己喜爱的商品,点击购买时,该商品就自动保存到你的购物车中,重复选购后,最后将选中的所有商品放在购物车中统一到付款台结账,这也是尽量让客户体验到现实生活中购物的感觉。服务器通过追踪每个用户的行动,以保证在结账时每件商品都物有其主。

主要涉及以下几点:

  1. 把商品添加到购物车,即订购
  2. 删除购物车中已定购的商品
  3. 修改购物车中某一本图书的订购数量
  4. 清空购物车
  5. 显示购物车中商品清单及数量、价格

实现购物车的关键在于服务器识别每一个用户并维持与他们的联系。但是 HTTP 协议是一种“无状态(Stateless)”的协议,因而服务器不能记住是谁在购买商品,当把商品加入购物车时,服务器也不知道购物车里原先有些什么,使得用户在不同页面间跳转时购物车无法“随身携带”,这都给购物车的实现造成了一定的困难。

目前购物车的实现主要是通过 cookie、session 或结合数据库的方式。下面分析一下它们的机制及作用。

1、cookie

cookie 是由服务器产生,存储在客户端的一段信息。它定义了一种 Web 服务器在客户端存储和返回信息的机制,cookie 文件它包含域、路径、生存期、和由服务器设置的变量值等内容。当用户以后访问同一个 Web 服务器时,浏览器会把 cookie 原样发送给服务器。通过让服务器读取原先保存到客户端的信息,网站能够为浏览者提供一系列的方便,例如在线交易过程中标识用户身份、安全要求不高的场合避免用户重复输入名字和密码、门户网站的主页定制、有针对性地投放广告等等。利用 cookie 的特性,大大扩展了 WEB 应用程序的功能,不仅可以建立服务器与客户机的联系,因为 cookie 可以由服务器定制,因此还可以将购物信息生成 cookie 值存放在客户端,从而实现购物车的功能。用基于 cookie 的方式实现服务器与浏览器之间的会话或购物车,有以下特点:

(1)cookie 存储在客户端,且占用很少的资源,浏览器允许存放 300 个 cookie,每个 cookie 的大小为 4KB,足以满足购物车的要求,同时也减轻了服务器的负荷;

(2)cookie 为浏览器所内置,使用方便。即使用户不小心关闭了浏览器窗口,只要在 cookie 定义的有效期内,购物车中的信息也不会丢失;

(3)cookie 不是可执行文件,所以不会以任何方式执行,因此也不会带来病毒或攻击用户的系统;

(4)基于 cookie 的购物车要求用户浏览器必须支持并设置为启用 cookie,否则购物车则失效;

(5)存在着关于 cookie 侵犯访问者隐私权的争论,因此有些用户会禁止本机的 cookie 功能。

2、session

session 是实现购物车的另一种方法。session 提供了可以保存和跟踪用户的状态信息的功能,使当前用户在 session 中定义的变量和对象能在页面之间共享,但是不能为应用中其他用户所访问,它与 cookie 最重大的区别是,session 将用户在会话期间的私有信息存储在服务器端,提高了安全性。在服务器生成 session 后,客户端会生成一个 sessionid 识别号保存在客户端,以保持和服务器的同步。这个 sessionid 是只读的,如果客户端禁止 cookie 功能,session 会通过在 URL 中附加参数,或隐含在表单中提交等其他方式在页面间传送。因此利用 session 实施对用户的管理则更为安全、有效。

同样,利用 session 也能实现购物车,这种方式的特点是:

(1)session 用新的机制保持与客户端的同步,不依赖于客户端设置;

(2)与 cookie 相比,session 是存储在服务器端的信息,因此显得更为安全,因此可将身份标示,购物等信息存储在 session 中;

(3)session 会占用服务器资源,加大服务器端的负载,尤其当并发用户很多时,会生成大量的 session,影响服务器的性能;

(4)因为 session 存储的信息更敏感,而且是以文件形式保存在服务器中,因此仍然存在着安全隐患。

3、结合数据库的方式

这也是目前较普遍的模式,在这种方式中,数据库承担着存储购物信息的作用,session 或 cookie 则用来跟踪用户。这种方式具有以下特点:

(1)数据库与 cookie 分别负责记录数据和维持会话,能发挥各自的优势,使安全性和服务器性能都得到了提高;

(2)每一个购物的行为,都要直接建立与数据库的连接,直至对表的操作完成后,连接才释放。当并发用户很多时,会影响数据库的性能,因此,这对数据库的性能提出了更高的要求;

(3)使 cookie 维持会话有赖客户端的支持。

各种方式的选择:

虽然 cookie 可用来实现购物车,但必须获得浏览器的支持,再加上它是存储在客户端的信息,极易被获取,所以这也限制了它存储更多,更重要的信息。所以一般 cookie 只用来维持与服务器的会话,例如国内最大的当当网络书店就是用 cookie 保持与客户的联系,但是这种方式最大的缺点是如果客户端不支持 cookie 就会使购物车失效。

Session 能很好地与交易双方保持会话,可以忽视客户端的设置。在购物车技术中得到了广泛的应用。但 session 的文件属性使其仍然留有安全隐患。

结合数据库的方式虽然在一定程度上解决了上述的问题,但从上面的例子可以看出:在这种购物流程中涉及到对数据库表的频繁操作,尤其是用户每选购一次商品,都要与数据库进行连接,当用户很多的时候就加大了服务器与数据库的负荷。

23.redis 消息队列先进先出需要注意什么

答:通常使用一个 list 来实现队列操作,这样有一个小限制,所以的任务统一都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念,我们就可以优先处理高级别的任务,实现方式有以下几种方式:

1)单一列表实现:队列正常的操作是 左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush),这样,从队列头部(右侧)获取任务时,取到的就是高优先级的任务(rpop)

2)使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列,获取任务时也很简单,redis 的 BRPOP 命令可以按顺序从多个队列中取值,BRPOP 会按照给出的 key 顺序查看,并在找到的第一个非空 list 的尾部弹出一个元素,redis> BRPOP list1 list2 0

list1 做为高优先级任务队列

list2 做为普通任务队列

这样就实现了先处理高优先级任务,当没有高优先级任务时,就去获取普通任务

方式 1 最简单,但实际应用比较局限,方式 3 可以实现复杂优先级,但实现比较复杂,不利于维护

方式 2 是推荐用法,实际应用最为合适

24.你负责的模块有哪些难题

答:在我负责的 B2B 电商项目中,当时我负责的是订单模块,由于客户一次选择了多家商户的商品,最终生成了一个订单,这样我们平台在给商户结算时出现了不知道这比费用应该给哪个商户,这时候我们小组经过讨论,需要涉及到订单拆分,也就是说用户点击支付后,如果有多件商品,并且不是同一家店铺那么 就要用到订单的拆分,比如如果有两件商品,并且不是同一店铺 就在原来的订单号下 在生成两个子订单号 并修改订单表中两件商品的订单号。最终实现了商品的分配管理,解决了我们的难题。

我觉得在开发过程中,遇到的难题无非是两个,一个是技术层次的,我认为,只要你有恒心,有热心,没有觉得不了的难题。另一个就是沟通问题,在任何地方任何时候沟通都是最重要的,尤其是我们做开发的,不沟通好,会影响整个项目的进度,我本人是个非常还沟通的人,所以这点上也没多大问题。

25.用户下单是怎么处理的

答:判断用户有没有登录,在没有登录的情况下,不允许下单。登陆后,可进行下单,并生成唯一的订单号,此时订单的状态为未支付。

26.电商的登录是怎么实现的

答:分为普通登录和第三方登录 这边主要说一下第三方登录吧,第三方登陆主要使用的是 author 协议,我就以 QQ 的第三方登陆为例来进行说明:当用户在我们的站点请求 QQ 的第三方登陆时,我们站点会引导用户跳转到 QQ 的登陆授权界面, 当用户输入 QQ 和密码成功登录以后会自动跳回到我们站点设置好的回调页面,并附带一个 code 参数,接着你使用 code 再次去请求 QQ 的授权页面,就可以从中获取到一个 access token(访问令牌),通过这个 access_token,我们可以调用 QQ 提供给我们的接口,比如获取 open_id,可以获取用户的基本信息。获取到之后,我们需要拿用户的授权信息和 open_id 和我们平台的普通用户进行绑定。这样不管是普通用户登陆还是第三方登陆用户,都可以实现登陆。

27.接口安全方面是怎么处理的

答:我们当时是这么做的,使用 HTTP 的 POST 方式,对固定参数+附加参数进行数字签名,使用的是 md5 加密,比如:我想通过标题获取一个息,在客户端使用 信息标题+日期+双方约定好的一个 key 通过 md5 加密生成一个签名(sign),然后作为参数传递到服务器端,服务器端使用同样的方法进行校验,如何接受过来的 sign 和我们通过算法算的值相同,证明是一个正常的接口请求,我们才会返回相应的接口数据。

28.用的什么技术实现短信发送,在哪调用

答:我主要用的第三方短信接口,在申请接口时进行相应信息的配置,然后在我们站点需要用到短信验证的地方进行调用,我们通常在用户注册时使用到。

29.在工作中遇到过什么困难?

答:总体来说:在工作我主要遇到这几个问题比较难处理:

① 我之前工作的时候发现经常会出现一些临时需求打乱了我的计划,搞得有时候这个任务还没完成,又得去做其他的任务,最后一天下来,大大小小的东西是很多,但是没有完成得非常好的,后面我总结了一下,我会把这些都添加优先级,遇到临时需求,按照优先级重新将已有任务和临时任务进行排版,保证在规定时间内有效率的完成优先级高的任务。

② 在做项目需求时候,遇到理解能力欠佳的人,沟通时容易被气到,影响自己的情绪,最后反倒还不能到达需要的效果。后面,每次到这种时候,我一般会借助一些纸质的、更加形象的东西,让双方都认同的、都能明白的一种方式来进行沟通,后面减少了很多不必须的麻烦。大家都知道,对于程序员来说,改需求是一件很痛苦的事情,所以前期的沟通工作很重要。

③ 还有一件事时,我以前的领导不太懂技术,所以每次出一个新的需求出来,总是要求我们在很短的时间内完成,完不成我们就会被怀疑能力有问题。当然,每个领导都希望自己的员工能够尽快的完成任务,降低成本,提高效率。这时候我会把我们的需求细化,把其中的重点、难点都列出来,做好时间规划,耐心的跟领导沟通,项目每个点的重要性和时间的花费比例,确保在这个规划的时间点内保质保量的完成任务。慢慢的也得到了领导的认可,其实领导也不是一味的不通情理,只要把东西计划好了,以最小的代价换取最高的价值,每个人都是很容易理解得

30.用户不登录,怎么直接加入购物车的

答:用户在不登录的情况下,可以把要购买商品的信息(如商品的 ID,商品的价格、商品的 sku_id,购买数量等关键数据)存到 COOKIE 里面,当登陆的情况下。把 COOKIE 里面的内容存到数据库,并清除 cookie 中的数据。

31.写过接口吗,怎么定义接口的

答:写过。接口分为两种:一种是数据型接口,一种是应用型接口。

数据型接口:是比抽象类更抽象的某种“结构”——它其实不是类,但是跟类一样的某种语法结构,是一种结构规范,规范我们类要以什么格式进行定义,一般用于团队比较大,分支比较多的情况下使用。

应用型接口:API(application interface) 数据对外访问的一个入口

我主要是参与的 APP 开发中接口的编写,客户端需要什么样的数据,我们就给他们提供相应的数据,数据以 json/xml 的格式返回,并且配以相应的接口文档。

32.sku 减库存

答:SKU = Stock Keeping Unit (库存量单位)

即库存进出计量的单位,可以是以件,盒,托盘等为单位。SKU 是库存量单位,区分单品。
在服装、鞋类商品中使用最多最普遍。例如纺织品中一个 SKU 通常表示:规格、颜色、款式。

在设计表时,不仅仅只有商品表,商品表中有个总库存,我们还需要涉及一张 SKU 表,里面有 SKU 库存和单价字段,用户每购买一件商品,实际上购买的都是 SKU 商品,这样在下订单成功后,应该根据所购买的商品的唯一的 SKU 号来进行相应的 SKU 库存的减少,当然商品的总库存保存在商品主表中,也需要减少总库存中的库存量。

33.库存设置?

答:库存分为商品总库存和 SKU 库存,往往商品总库存的为 SKU 库存的总和。一般在商城的后台对货品设置最高库存及最低库存后,当前库存数量与最高、最低两者比较,超出库存或者低于库存的,则被统计成报表形式反映,便于用户掌握货品库存超、短缺状态及数量。

34.订单、库存两个表 如何保证数据的一致性?

答:在一个电子商务系统中,正常的应该是订单生成成功后,相应的库存进行减少。必须要保证两者的一致性,但有时候因为某些原因,比如程序逻辑问题,并发等问题,导致下单成功而库存没有减少的情况。这种情况我们是不允许发生的,MySQL 中的事务刚好可以解决这一问题,首先得选择数据库的存储引擎为 innoDB,事务规定了只有下订单完成了,并且相应的库存减少了才允许提交事务,否则就事务回滚,确保数据一致性。

35.O2O 用户下单,c 端下单,如何保证 b a 端数据一致?

答:O2O 为线上和线下模式,O2O 模式奉行的是“线上支付+实体店消费”的消费模式,即消费者在网上下单完成支付后,凭消费凭证到实体店消费。O2O 模式是把商家信息和支付程序放在线上进行,而把商品和服务兑现放在线下,也就是说 O2O 模式适用于快递无法送达的有形产品。数据一致性的问题是 O2O 行业中最常见的问题,我们可以类似于数据库的主从复制的思路来解决这个问题。O2O 有个供应商系统,类似于主服务器,在 C 端(从服务器)下单时,数据同步更新到供应商系统端,b、a 实时从供应商系统中拉取数据进行同步,比如利用定时任务,定时拉取数据进行同步。

36.Redis 如何防止高并发

答:其实 redis 是不会存在并发问题的,因为他是单进程的,再多的 command 都是 one by one 执行的。我们使用的时候,可能会出现并发问题,比如 get 和 set 这一对。

redis 为什么会有高并发问题

redis 的出身决定

Redis 是一种单线程机制的 nosql 数据库,基于 key-value,数据可持久化落盘。由于单线程所以 redis 本身并没有锁的概念,多个客户端连接并不存在竞争关系,但是利用 jedis 等客户端对 redis 进行并发访问时会出现问题。发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。

同时,单线程的天性决定,高并发对同一个键的操作会排队处理,如果并发量很大,可能造成后来的请求超时。

在远程访问 redis 的时候,因为网络等原因造成高并发访问延迟返回的问题。

解决办法

在客户端将连接进行池化,同时对客户端读写 Redis 操作采用内部锁 synchronized。

服务器角度,利用 setnx 变向实现锁机制。

37.秒杀当中的细节你是怎么得出来的

答:通过性能测试及模拟秒杀场景。每个问题都经过反复测试,不断的发现问题,不断的解决。

38.做秒杀用什么数据库,怎么实现的。

答:因为秒杀的一瞬间,并发非常大,如果同时请求数据库,会导致数据库的压力非常大,导致数据库的性能急剧下降,更严重的可能会导致数据库服务器宕机。这时候一般采用内存高速缓存数据库 redis 来实现的,redis 是非关系型数据库,redis 是单线程的,通过 redis 的队列可以完成秒杀过程。

39.支付宝流程怎么实现的

答:首先要有一个支付宝账号,接下来向支付宝申请在线支付业务,签署协议。协议生效后有支付宝一方会给网站方一个合作伙伴 ID,和安全校验码,有了这两样东西就可以按照支付宝接口文档开发支付宝接口了,中间主要涉及到一个安全问题。整个流程是这样的:我们的网站通过 post 传递相应的参数(如订单总金额,订单号)到支付页面,支付页面把一系列的参数经过处理,以 post 的方式提交给支付宝服务器,支付宝服务器进行验证,并对接收的数据进行处理,把处理后的结果返回给我们网站设置的异步和同步回调地址,通过相应的返回参数,来处理相应的业务逻辑,比如返回的参数代表支付成功,更改订单状态。

40.什么是单点登录?

答:单点登录 SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。

41.什么情况下使用缓存

答:当用户第一次访问应用系统的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--ticket;用户再访问别的应用的时候,就会将这个 ticket 带上,作为自己认证的凭据,应用系统接受到请求之后会把 ticket 送到认证系统进行校验,检查 ticket 的合法性。如果通过校验,用户就可以在不用再次登录的情况下访问应用系统 2 和应用系统 3 了。

实现主要技术点:

  1. 两个站点共用一个数据验证系统
  2. 主要通过跨域请求的方式来实现验证及 session 处理。

42.怎么实现第三方登录?

答:第三方登陆主要是基于 author 协议来实现,下面简单说下实现流程:

  1. 首先我们需要以开发者的身份向第三方登陆平台申请接入应用,申请成功后,我们会获得一个 appID 和一个 secrectID.
  2. 当我们的网站需接入第三方登陆时,会引导用户跳转到第三方的登陆授权页面,此时把之前申请的 appID 和 secrectID 带给登陆授权页面。
  3. 用户登陆成功后即得到授权,第三方会返回一个临时的 code 给我们的网站。
  4. 我们的网站接受到 code 后,再次向我们的第三方发起请求,并携带接收的 code,从第三方获取 access_token.
  5. 第三方处理请求后,会返回一个 access_token 给我们的网站,我们的网站获取到 access_token 后就可以调用第三方提供的接口了,比如获取用户信息等。最后把该用户信息存入到我们站点的数据库,并把信息保存到 session 中,实现用户的第三方登陆。

43.如何处理负载、高并发?(好好看看,经常问到,能回答到主要的东西即可)

答:从低成本、高性能和高扩张性的角度来说有如下处理方案:

1、HTML 静态化

其实大家都知道,效率最高、消耗最小的就是纯静态化的 html 页面,所以我们尽可能使我们的 网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。

2、图片服务器分离

把图片单独存储,尽量减少图片等大流量的开销,可以放在一些相关的平台上,如骑牛等

3、数据库集群和库表散列及缓存

数据库的并发连接为 100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如 memcache、redis。

4、镜像:

尽量减少下载,可以把不同的请求分发到多个镜像端。

5、数据库优化

6、负载均衡:

Apache 的最大并发连接为 1500,只能增加服务器,可以从硬件上着手,如 F5 服务器。当然硬件的成本比较高,我们往往从软件方面着手。

负载均衡 (Load Balancing) 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力,同时能够提高网络的灵活性和可用性。目前使用最为广泛的负载均衡软件是 Nginx、LVS、HAProxy。我分别来说下三种的优缺点:

Nginx 的优点是:

  1. 工作在网络的 7 层之上,可以针对 http 应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比 HAProxy 更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx 单凭这点可利用的场合就远多于 LVS 了。
  2. Nginx 对网络稳定性的依赖非常小,理论上能 ping 通就就能进行负载功能,这个也是它的优势之一;相反 LVS 对网络稳定性依赖比较大,这点本人深有体会;
  3. Nginx 安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS 的配置、测试就要花比较长的时间了,LVS 对网络依赖比较大。
  4. 可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比 LVS 相对小些。
  5. Nginx 可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持 url 来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx 会把上传切到另一台服务器重新处理,而 LVS 就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。
  6. Nginx 不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的 Web 应用服务器。LNMP 也是近几年非常流行的 web 架构,在高流量的环境中稳定性也很好。
  7. Nginx 现在作为 Web 反向加速缓存越来越成熟了,速度比传统的 Squid 服务器更快,可以考虑用其作为反向代理加速器。
  8. Nginx 可作为中层反向代理使用,这一层面 Nginx 基本上无对手,唯一可以对比 Nginx 的就只有 lighttpd 了,不过 lighttpd 目前还没有做到 Nginx 完全的功能,配置也不那么清晰易读,社区资料也远远没 Nginx 活跃。
  9. Nginx 也可作为静态网页和图片服务器,这方面的性能也无对手。还有 Nginx 社区非常活跃,第三方模块也很多。

Nginx 的缺点是:

  1. Nginx 仅能支持 http、https 和 Email 协议,这样就在适用范围上面小些,这个是它的缺点。
  2. 对后端服务器的健康检查,只支持通过端口来检测,不支持通过 url 来检测。不支持 Session 的直接保持,但能通过 ip_hash 来解决。

LVS:使用 Linux 内核集群实现一个高性能、高可用的负载均衡服务器,它具有很好的可伸缩性(Scalability)、可靠性(Reliability)和可管理性(Manageability)。

LVS 的优点是:

  1. 抗负载能力强、是工作在网络 4 层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和 cpu 资源消耗比较低。
  2. 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。
  3. 工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如 LVS+Keepalived,不过我们在项目实施中用得最多的还是 LVS/DR+Keepalived。
  4. 无流量,LVS 只分发请求,而流量并不从它本身出去,这点保证了均衡器 IO 的性能不会受到大流量的影响。
  5. 应用范围比较广,因为 LVS 工作在 4 层,所以它几乎可以对所有应用做负载均衡,包括 http、数据库、在线聊天室等等。

LVS 的缺点是:

  1. 软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是 Nginx/HAProxy+Keepalived 的优势所在。
  2. 如果是网站应用比较庞大的话,LVS/DR+Keepalived 实施起来就比较复杂了,特别后面有 Windows Server 的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived 就简单多了。

HAProxy 的特点是:

  1. HAProxy 也是支持虚拟主机的。
  2. HAProxy 的优点能够补充 Nginx 的一些缺点,比如支持 Session 的保持,Cookie 的引导;同时支持通过获取指定的 url 来检测后端服务器的状态。
  3. HAProxy 跟 LVS 类似,本身就只是一款负载均衡软件;单纯从效率上来讲 HAProxy 会比 Nginx 有更出色的负载均衡速度,在并发处理上也是优于 Nginx 的。
  4. HAProxy 支持 TCP 协议的负载均衡转发,可以对 MySQL 读进行负载均衡,对后端的 MySQL 节点进行检测和负载均衡,大家可以用 LVS+Keepalived 对 MySQL 主从做负载均衡。
  5. HAProxy 负载均衡策略非常多,HAProxy 的负载均衡算法现在具体有如下 8 种:

① roundrobin,表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;

② static-rr,表示根据权重,建议关注;

③ leastconn,表示最少连接者先处理,建议关注;

④ source,表示根据请求源 IP,这个跟 Nginx 的 IP_hash 机制类似,我们用其作为解决 session 问题的一种方法,建议关注;

⑤ ri,表示根据请求的 URI;

⑥ rl_param,表示根据请求的 URl 参数’balance url_param’ requires an URL parameter name;

⑦ hdr(name),表示根据 HTTP 请求头来锁定每一次 HTTP 请求;

⑧ rdp-cookie(name),表示根据据 cookie(name)来锁定并哈希每一次 TCP 请求。

Nginx 和 LVS 对比的总结:

  1. Nginx 工作在网络的 7 层,所以它可以针对 http 应用本身来做分流策略,比如针对域名、目录结构等,相比之下 LVS 并不具备这样的功能,所以 Nginx 单凭这点可利用的场合就远多于 LVS 了;但 Nginx 有用的这些功能使其可调整度要高于 LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。
  2. Nginx 对网络稳定性的依赖较小,理论上只要 ping 得通,网页访问正常,Nginx 就能连得通,这是 Nginx 的一大优势!Nginx 同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS 就比较依赖于网络环境,目前来看服务器在同一网段内并且 LVS 使用 direct 方式分流,效果较能得到保证。另外注意,LVS 需要向托管商至少申请多一个 ip 来做 Visual IP,貌似是不能用本身的 IP 来做 VIP 的。要做好 LVS 管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个 HTTP 那么简单了。
  3. Nginx 安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS 的安装和配置、测试就要花比较长的时间了;LVS 对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。
  4. Nginx 也同样能承受很高负载且稳定,但负载度和稳定度差 LVS 还有几个等级:Nginx 处理所有流量所以受限于机器 IO 和配置;本身的 bug 也还是难以避免的。
  5. Nginx 可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前 LVS 中 ldirectd 也能支持针对服务器内部的情况来监控,但 LVS 的原理使其不能重发请求。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx 会把上传切到另一台服务器重新处理,而 LVS 就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。
  6. Nginx 对请求的异步处理可以帮助节点服务器减轻负载,假如使用 apache 直接对外服务,那么出现很多的窄带链接时 apache 服务器将会占用大 量内存而不能释放,使用多一个 Nginx 做 apache 代理的话,这些窄带链接会被 Nginx 挡住,apache 上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用 squid 也有相同的作用,即使 squid 本身配置为不缓存,对 apache 还是有很大帮助的。
  7. Nginx 能支持 http、https 和 email(email 的功能比较少用),LVS 所支持的应用在这点上会比 Nginx 更多。在使用上,一般最前端所采取的策略应是 LVS,也就是 DNS 的指向应为 LVS 均衡器,LVS 的优点令它非常适合做这个任务。重要的 ip 地址,最好交由 LVS 托管,比如数据库的 ip、webservice 服务器的 ip 等等,这些 ip 地址随着时间推移,使用面会越来越大,如果更换 ip 则故障会接踵而至。所以将这些重要 ip 交给 LVS 托管是最为稳妥的,这样做的唯一缺点是需要的 VIP 数量会比较多。Nginx 可作为 LVS 节点机器使用,一是可以利用 Nginx 的功能,二是可以利用 Nginx 的性能。当然这一层面也可以直接使用 squid,squid 的功能方面就比 Nginx 弱不少了,性能上也有所逊色于 Nginx。Nginx 也可作为中层代理使用,这一层面 Nginx 基本上无对手,唯一可以撼动 Nginx 的就只有 lighttpd 了,不过 lighttpd 目前还没有能做到 Nginx 完全的功能,配置也不那么清晰易读。另外,中层代理的 IP 也是重要的,所以中层代理也拥有一个 VIP 和 LVS 是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日 PV 小于 1000 万),用 Nginx 就完全可以了,如果机器也不少,可以用 DNS 轮询,LVS 所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用 LVS。

44.做秒杀时锁表考虑到没有?

答:考虑到了,当时我们做秒杀时考虑了好几种方案,其中有一种就是使用事务加上排他锁来实现。

架构类的东西接触过吗?

有接触过,曾经自己在自己的服务器上配置过。我以前做过以下几个架构方面的配置和测试;

  1. 数据库的读写分离、主从复制及集群。
  2. Nginx 负载均衡
  3. redis 集群及主从

45.封装过一个简单的框架

答;封装过一个简单的 MVC 框架,主要分为 3 层,控制器层和模型层视图层,以及路由的分配和入口文件,模板引擎,单例模式、工厂模式,第三方类库的引入等。

46.谈谈对 MVC 的认识

答:核心思想是:视图和用户交互通过事件导致控制器改变 控制器改变导致模型改变 或者控制器同时改变两者 模型改变 导致视图改变 或者视图改变 潜在的从模型里面获得参数 来改变自己。他的好处是可以将界面和业务逻辑分离。

Model(模型),是程序的主体部分,主要包含业务数据和业务逻辑。在模型层,还会涉及到用户发布的服务,在服务中会根据不同的业务需求,更新业务模型中的数据。

View(视图),是程序呈现给用户的部分,是用户和程序交互的接口,用户会根据具体的业务需求,在 View 视图层输入自己特定的业务数据,并通过界面的事件交互,将对应的输入参数提交给后台控制器进行处理。

Contorller(控制器),Contorller 是用来处理用户 输入数据,已经更新业务模型的部分。控制器中接收了用户与界面交互时传递过来的数据,并根据数据业务逻辑来执行服务的调用和更新业务模型的数据和状态。

47.session 与 cookie 的区别

答:

1、cookie 数据存放在第三方应用的浏览器上,session 数据放在服务器上。
2、cookie 不是很安全,别人可以分析存放在本地的 COOKIE,进行 COOKIE 欺骗

考虑到安全应当使用 session。
3、session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能

考虑到减轻服务器性能方面,应当使用 COOKIE。
4、单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
5、所以个人建议:
将登陆信息等重要信息存放为 SESSION
其他信息如果需要保留,可以放在 COOKIE

48.echo(),print(),print_r()的区别

答:echo 可以一次输出多个值,多个值之间用逗号分隔。echo 是语言结构(language construct),而并不是真正的函数,因此不能作为表达式的一部分使用。echo 是 php 的内部指令,不是函数,无返回值。

print():函数 print()打印一个值(它的参数),如果字符串成功显示则返回 true,否则返回 false。只能打印出简单类型变量的值(如 int,string),有返回值

printf():源于 C 语言中的 printf()。该函数输出格式化的字符串。

print_r()和 var_dump()

print_r()可以把字符串和数字简单地打印出来,而数组则以括起来的键和值得列表形式显示,并以 Array 开头。但 print_r()输出布尔值和 NULL 的结果没有意义,因为都是打印"\n"。因此用 var_dump()函数更适合调试。print_r 是函数,可以打印出比较复杂的变量(如数组,对象),有返回值

var_dump()判断一个变量的类型与长度,并输出变量的数值,如果变量有值输的是变量的值并回返数据类型。此函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。

49.说一下单引号双引号?

答:①单引号内部的变量不会执行, 双引号会执行

②单引号解析速度比双引号快。

③单引号只能解析部分特殊字符,双引号可以解析所有特殊字符。

50.索引的优缺点

答:1、优点:

a)可以保证数据库表中每一行的数据的唯一性

b)可以大大加快数据的索引速度

c)加速表与表之间的连接,物别是在实现数据的参考完事性方面特别有意义

d)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间

f)通过使用索引,可以在时间查询的过程中,使用优化隐藏器,提高系统的性能

2、 缺点:

a) 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加

b) 索引需要占物理空间,除了数据表占用数据空间之外,每一个索引还要占用一定的物理空间,如果需要建立聚簇索引,那么需要占用的空间会更大

c) 以表中的数据进行增、删、改的时候,索引也要动态的维护,这就降低了整数的维护速度

d) 建立索引的原则

e) 在经常需要搜索的列上,可以加快搜索的速度

f) 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构

g) 在经常用在连接的列上,这些列主要是一外键,可以加快连接的速度

h) 在经经常需要根据范围进行搜索的列上创建索引,国为索引已经排序,其指定的范围是连续的

i) 在经常需要排序的列上,国为索引已经排序,这样井底可以利用索引的排序,加快排序井底时间

j) 在经常使用在 where 子句中的列上,加快条件的判断速度

51.get 和 post 的区别

答:

  1. get 是从服务器上获取数据,post 是向服务器传送数据。
  2. get 是把参数数据队列加到提交表单的 ACTION 属性所指的 URL 中,值和表单内各个字段一一对应,在 URL 中可以看到。post 是通过 HTTP post 机制,将表单内各个字段与其内容放置在 HTML HEADER 内一起传送到 ACTION 属性所指的 URL 地址。用户看不到这个过程。
  3. get 传送的数据量较小,不能大于 2KB。post 传送的数据量较大,一般被默认为不受限制。
  4. get 安全性非常低,post 安全性较高。但是执行效率却比 Post 方法好。

52.如何修改 session 的生存时间

答:一:在 php.ini 中设置 session.gc_maxlifetime = 1440 //默认时间

二:代码实现

$lifeTime = 24 * 3600; // 保存一天
session_set_cookie_params($lifeTime);
session_start();

53.Linux 基本命令,目录结构

答:arch 显示机器的处理器架构(1)

uname -m 显示机器的处理器架构(2)

uname -r 显示正在使用的内核版本

dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI)

hdparm -i /dev/hda 罗列一个磁盘的架构特性

hdparm -tT /dev/sda 在磁盘上执行测试性读取操作

cat /porc/cpuinfo 显示 CPU info 的信息

cat /porc/interrupts 显示中断

cat /porc/meminfo 校验内存使用

cat /porc/swaps 显示哪些 swap 被使用

cat /porc/verion 显示内核的版本

cat /porc/net/dev 显示网络适配器及统计

cat /porc/mounts 显示已加载的文件系统

date 显示系统日期

cal 2007 显示 2007 年的日历表

date 041217002007.00 设置日期和时间 -月日时分年.秒

clock -w 将时间修改保存到 BIOS

文件搜索

find / -name file1 从 '/'开始进入根文件系统搜索文件和目录

locate *.ps 寻找以 '.ps'结尾的文件 -先运行'updatedb'命令

whereis halt 显示一个二进制文件、源码或 man 的位置

which halt 显示一个二进制文件或可执行文件的完整路径

挂载一个文件系统

mount /dev/hda2 /mnt/hda2 挂载一个叫做 hda2 的盘- 确定目录'/ mnt/hda2' 已经存在

umount /dev/hda2 卸载一个叫做 hda2 的盘- 先从挂载点'/ mnt/hda2' 退出

追加命令

  1. linux 里把文件/etc/aaa 中的内容追加到/usr/bbb 中的内容的后面
    sudo cat /etc/aaa >>/usr/bbb
  2. 更改/etc/index.html 的文件所有者为 apache,文件群组为 apache
    sudo chmod apache:apache /etc/index.html
  3. 更改/etc/index.html 的所有者权限为读取、写入、执行。群组权限为读取。其他权限为读取
    sudo chmod 744 /etc/index.html
  4. 删除/etc 下名为 hello 的文件
    sudo rm /etc/index.html

当然,如果你是以 orot 用户执行以上操作,可以去掉前边的 sudo!

df -hl 查看磁盘剩余空间

df -h 查看每个根路径的分区大小

du -sh [目录名] 返回该目录的大小

du -sm [文件夹] 返回该文件夹总 M 数

关机 (系统的关机、重启以及登出)

shutdown -h now 关闭系统(1)

init 0 关闭系统(2)

telinit 0 关闭系统(3)

shutdown -h hour:minutes & 按预定时间关闭系统

shutdown -c 取消按预定时间关闭系统

shutdown -r now 重启(1)

reboot 重启(2)

logout 注销

文件和目录

pwd 显示工作路径

ls 查看目录中的文件

ls -F 查看目录中的文件

ls -l 显示文件和目录的详细资料

ls -a 显示隐藏文件

ls [0-9] 显示包含数字的文件名和目录名

tree 显示文件和目录由根目录开始的树形结构(1)

lstree 显示文件和目录由根目录开始的树形结构(2)

mkdir dir1 创建一个叫做 'dir1'的目录'

磁盘空间

df -h 显示已经挂载的分区列表

ls -lSr |more 以尺寸大小排列文件和目录

du -sh dir1 估算目录 'dir1'已经使用的磁盘空间'

下载、解压

1)对于.tar 结尾的文件
  tar -xf all.tar

2)对于.gz 结尾的文件
  gzip -d all.gz
  gunzip all.gz

zip all.zip *.jpg

这条命令是将所有.jpg 的文件压缩成一个 zip 包

unzip all.zip

这条命令是将 all.zip 中的所有文件解压出来

下载命令

wget + 空格 +要下载文件的 url 路径

=====================================

Shell 脚本

必须以 #!/bin/sh 开头

简单例子:判断这个目录下有没有文件(File)

#!/bin/bash
Num=ls -al /opt |grep "^-"|wc -l
if [ $Num != 0 ]
then echo "/opt has $Num files"
else
echo "/opt has none file"
fils -al /opt |grep "^-"|wc -l 这个命令能够统计文件个数 为 0 就是没有文件 非零就是有文件

54..memcache 缓存什么数据

答:一、经常被读取并且实时性要求不强可以等到自动过期的数据。例如网站首页最新文章列表、某某排行等数据。

二、经常被读取并且实时性要求强的数据。比如用户的好友列表,用户文章列表,用户阅读记录等。

三、统计类缓存,比如文章浏览数、网站 PV 等。

四、活跃用户的基本信息或者某篇热门文章。

五、session 数据

55.魔术方法、魔术常量

答:1、__construct()
实例化对象时被调用,当 __construct 和以类名为函数名的函数同时存在时,__construct 将被调用,另一个不被调用。

2、__destruct()
当删除一个对象或对象操作终止时被调用。

3、__call()
对象调用某个方法,若方法存在,则直接调用;若不存在,则会去调用 __call 函数。

4、__get()
读取一个对象的属性时,若属性存在,则直接返回属性值;若不存在,则会调用 __get 函数。

5、__set()
设置一个对象的属性时,若属性存在,则直接赋值;若不存在,则会调用 __set 函数。

6、__clone()
克隆对象时被调用。如:t=newTest();t1=clone $t;bj;

7、__clone()
克隆对象时被调用。如:t=newTest();t1=clone $t;

8、__sleep()
serialize 之前被调用。若对象比较大,想删减一点东东再序列化,可考虑一下此函数。

9、__wakeup()
unserialize 时被调用,做些对象的初始化工作。

10、__isset()
检测一个对象的属性是否存在时被调用。如:isset($c->name)。

11、__unset()
unset 一个对象的属性时被调用。如:unset($c->name)。

12、__set_state()
调用 var_export 时,被调用。用 __set_state 的返回值做为 var_export 的返回值。

13、__autoload()
实例化一个对象时,如果对应的类不存在,则该方法被调用。

魔术常量:

1、__LINE__
返回文件中的当前行号。

2、__FILE__
返回文件的完整路径和文件名。如果用在包含文件中,则返回包含文件名。自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路径,而在此之前的版本有时会包含一个相对路径。

3、__FUNCTION__
返回函数名称(PHP 4.3.0 新加)。自 PHP 5 起本常量返回该函数被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。

4、__CLasS__
返回类的名称(PHP 4.3.0 新加)。自 PHP 5 起本常量返回该类被定义时的名字(区分大小写)。在 PHP 4 中该值总是小写字母的。

5、__METHOD__
返回类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。

6、__set()当程序试图写入一个不存在或者不可见的成员变量时,__set()方法包含两个参数,分别表示变量名称和变量值,两个参数都不可省略

7、__get()当程序试图调用一个未定义或不可见的成员变量时,__get()方法有一个参数,表示要调用的变量名

__sleep() 常用于提交未提交的数据,或类似的清理操作如果有一些很大的对象,但不需要全部保存,这个功能就很好用。

__construct() 在类实例化对象的同时执行该函数

__distruct() 在类实例化的对象销毁时执行

__call()对象调用某个方法,若方法存在,则直接调用;若不存在,则会去调用 __call 函数。

__clone()克隆对象时被调用。如:$t=new Test();$t1=clone $t;

__toString()打印一个对象的时被调用。如 echo $obj;或 print $obj;

__isset()检测一个对象的属性是否存在时被调用。如:isset($c->name)。

__unset()unset 一个对象的属性时被调用。如:unset($c->name)。

__autoload()实例化一个对象时,如果对应的类不存在,则该方法被调用。

56.接口和抽象类的区别是什么?

答:抽象类是一种不能被实例化的类,只能作为其他类的父类来使用。抽象类是通过关键字 abstract 来声明的。

抽象类与普通类相似,都包含成员变量和成员方法,两者的区别在于,抽象类中至少要包含一个抽象方法,抽象方法没有方法体,该方法天生就是要被子类重写的。
抽象方法的格式为:abstract function abstractMethod();

接口是通过 interface 关键字来声明的,接口中的成员常量和方法都是 public 的,方法可以不写关键字 public,接口中的方法也是没有方法体。接口中的方法也天生就是要被子类实现的。

抽象类和接口实现的功能十分相似,最大的不同是接口能实现多继承。在应用中选择抽象类还是接口要看具体实现。

子类继承抽象类使用 extends,子类实现接口使用 implements。

57.什么是队列?排它锁,Myisam 死锁如何解决?

答:在默认情况下 MYisam 是表级锁,所以同时操作单张表的多个动作只能以队列的方式进行;

排它锁又名写锁,在 SQL 执行过程中为排除其它请求而写锁,在执行完毕后会自动释放;

死锁解决:先找到死锁的线程号,然后杀掉线程 ID

58.bootstrap 框架有哪些优点?

答:bootstrap 是一款 web 开发框架,它由 CSS,JavaScript,Html,三部分构成,它简洁灵活,使得 web 开发更加的快捷

优点:

①节省时间: 使用 bootstrap 框架,可以大大的节省项目开发时间,它包含了很多现成的代码,如果需要使用,只需要找到合适的代码,插入合适的位置即可,此外,CSS 是使用 LESS 编写,很多样式和设计都已经设计完成了

②定制化: bootstrap 可以根据自己的项目,留取框架中自己需要的部分

③设计合理:

  1. 栅格系统: bootstrap 定义 12 格栅系统,在页面已经完成时,你可以根据合适的网格,以自己的需求改变行数和布局大小,样式已经开发完成了,只需要把代码放入合适的 HTML 代码位置即可
  2. LESS: LESS 是基于 CSS 之上的高级语言,其目的是使得 CSS 开发更加灵活,更加强大
  3. JavaScript:bootstrap 提供 JavaScript 库,该库超越了基本的架构和样式,开发者可以轻松的操作窗口警告框,工具提示框等,可避免了我们费神费力的写脚本
  4. 一致性: bootstrap 可以保证界面在不同平台的统一性,无论实在 IE,Chrome 等
  5. 持续更新: bootstrap 在不断的改进,更具规律性和持续性
  6. 响应式: 无论是在 PC 端还是移动端,都可以保持界面的一致性
  7. 文档多: bootstrap 的非常多

    59.客户端如何传递参数

        1.URL参数传递

        2.Request Body传递:form-urlencode 、form-data、application/json

    60.php获取参数的方式

        1.form-urlencode 、form-data   传递方式可以通过  $_GET    $_POST 方式获取

        2.application/json传递方式可以通过file_get_contents("php://input")方式获取



【原创】 Git使用
30 06 2020

一、Git基本使用

        1、git工作流程图

        image.png


        2、git安装

        默认安装,略过...


        3、基本配置

        ① 打开git bash 

        ② 设置用户信息

        git config  --global user.name  "名字"

        git config  --global user.email  "你的邮箱"

        ③ 查看配置信息

        git config  --global user.name

        git config  --global user.email

        ④ 为常用指令设置别名

        ④.① 打开用户目录,创建bashrc文件。部分windows不允许用户创建.开头的文件,可以使用gitBash,执行touch ~/.bashrc

        image.png

        image.png

        ④.② 在.bashrc文件输入以下内容 :

        #用于输出git提交日志

        alias git-log='git log --pretty=oneline --all --graph --abbrev-commit'

        #用于输出当前目录所有文件及基本信息

        alias ll='ls -al'

        ④.③ 打开gitBash,执行source  ~/.bashrc

        ⑤ 解决gitbash乱码问题

        ⑤.① 打开gitbash执行下面命令

        git config --global core.quotepath false

        image.png

        ⑤.② 打开下面文件输入以下命令,  ${git_home} 安装的git目录

        image.png

        export LANG="zh_CN.UTF-8"

        export LC_ALL="zb_CN.UTF-8"


        4、获取本地仓库

        image.png

        

        5、基本操作命令

        git工作目录下对于文件的修改(增加、删除、更新)会存在几个状态,这些修改的状态会随着我们执行git命令发生变化

        image.png

        ① 查看修改的状态 

        命令:git status 

        image.png

        ② 添加到工作暂存区

        命令:git add  (文件名,这里不一个个去添加了,直接git add .)

        image.png

        再次查看状态:状态是即将被提交,已经进入到暂存区(提交到仓库之前的一个缓存区域)

        image.png

        ③ 提交到仓

        命令:git commit -m "修改记录"

        image.png

        再次查看状态:

        image.png

        ④ 查看提交日志

        命令:git log [option]     git-log

        image.png

        image.png

        image.png

        修改了文件以后:

        查看修改的文件,再次提交到暂存区

        image.png

        image.png

        把修改的文件提交到仓库,查看提交日志有两次提交

        image.png

        带参数的查看日志:

        git log --pretty=online --abbrev-commit --all --graph

        image.png

        ⑤ 版本回退

        命令:git reset --hard  commitID

        commitID可以通过git-log  或者git  log 查看

        image.png

        返回去

        image.png

        查看已经删除的记录:如果是clear以后,忘记了commitID,可以通过  git reflog 命令查看分析

        命令:git reflog

        image.png

        ⑥ 添加文件至忽略列表(不被git管理)

        一些文件不需要git管理,也不希望它们出现在为跟踪文件列表,我们可以创建一个.gitignore的文件,列出要忽略的文件模式

        image.png

        

        6、分支

        几乎所有的版本控制系统都以某种形式支持分支,使用分支意味着你可以把你的工作从开发主线上分离开来进行重大的bug修改、开发新的功能,以免影响开发主线

        ① 查看本地分支

        命令:git branch 

        查看远端分支

        命令:git branch -a

        image.png

        ② 创建分支

        命令:git branch   分支名

        image.png

        再查看,现在有2个分支

        image.png

        ③ 切换分支

        命令:git checkout  分支名

        image.png

        HEAD指向谁,谁就是当前分支

        image.png

        ④ 切换到一个不存在的分支(创建并切换)

        命令:git checkout -b 分支名

        image.png

        ⑤ 合并分支,  将一个分支上的提交可以合并到另一个分支

        命令:git merge  分支名

        image.png

        ⑥ 删除分支,  不能删除当前分支只能删除其他分支

        命令1:git branch -d  分支名   删除分支时需要做各种检查

        命令2:git branch -D  分支名   不做任何检查,强制删除  

        image.png

        ⑦ 解决冲突

        当两个分支上对文件的修改可能会存在冲突,例如同时修改了同一个文件的同一行,这时就需要手动解决冲突,解决冲突步骤如下:

        image.png

        来看例子:

        image.png

        image.png

        image.png

        简单粗暴手动修改成5

        image.png

        image.png

        ⑧ 分支在开发中使用的原则与流程

        image.png

        图示如下:

        image.png

        

        7、仓库托管

        ① 托管仓库

        常见的托管仓库有GitHub、码云、GitLab等

        ② 注册码云

        略过......

        ③ 创建远程仓库

        image.png

        ④ 配置SSH公钥

        ④.① 生成SSH公钥 

        ssh-keygen -t rsa   不断回车,如果公钥已经存在,则自动覆盖

        ④.② 获取公

        cat ~/.ssh/id_rsa.pub

        ssh-keygen -

        ④.③ 验证是否配置成功

        ssh -T git@gitee.com   按提示输入yes

        ⑤ 添加远端仓库地址

        git remote add origin  ssh地址

        image.png

        查看远端仓库

        image.png

        ⑥ 推送到远端仓库

        git push origin master

        image.png


        image.png

        提交到远端指定分支名:

        git push 远端名称  本地分支名:远端分支名

        git push origin master:develop

        image.png

        ⑦ 删除指定的远程仓库

        git remote rm 远程仓库名

        image.png

        ⑧ 克隆

        git clone 远端地址  起别名(不指定别名就默认)

        ⑨ 抓取和拉取

        ⑨.① 抓取

        命令:git fetch [remote name] [branch name]

        抓取指令就是将远端仓库的更新都抓取到本地,不会进行合并

        如果不指定远端名称和分支名,则抓取所有分支


        ⑨.② 拉取

        命令:git pull [remote name] [branch name]

        拉取指令就是将远端仓库的修改都拉取到本地并进行自动合并,等同于fetch + merge

        如果不指定远端名称和分支,则抓取所有并更新当前分支

        image.png


        8、解决合并冲突

        image.png

        注意:每次提交代码之前,先 git pull 别人的修改到本地

        9、在IDE中使用git

        ⑨.① 点击文件  -> 设置

        image.png

        ⑨.② 点击Git   ->  点击测试   -> 显示Git版本号表示成功,如果失败则手动指定git安装位置

        image.png

        ⑨.③ 在IDE中操作Git

        image.png

        image.png

        image.png

        image.png


        10、服务器上搭建git仓库

        ⑩.① 安装git

        image.png

        image.png

        ⑩.② 配置git

        a、创建用户组

        image.png

        b、创建用户账号

        image.png

        c、设置账号密码

        image.png

        ⑩.③ git仓库初始化

        a、创建目录,修改目录归属者

        image.png

        b、初始化git仓库

        image.png

        c、修改仓库归属者

        image.png

        ⑩.④ git仓库的使用

        

        

        


        




        

        



【原创】 假鱼香料
27 06 2020

        国庆回家发现了一个好东西,我们叫它“鱼香草”(又叫藿香叶)。

        在我们老家那地方,它是很多80后、90后的回忆。小的时候农村没有什么营养品,没有牛奶,酸菜、辣椒、田边山头野菜便是我们记忆中的美味。从高二第一次出去打工之后,就很少在家里待过,难得回家一趟,趁这个机会,我又在后台一字一字把它记录了下来。

        这个菜我们叫它“假鱼香料”,这也是一个超级下饭菜,以下操作记录全过程。

        第一步、准备材料:摘鱼香叶,准备酸菜、酸萝卜、泡南充菜都可以、泡椒、姜、鲜辣椒、大蒜等。鱼香叶洗干净之后切碎,酸萝卜、酸菜、泡椒、鲜辣椒(辣椒剁成渣渣)、大蒜切碎。


    

假鱼香料1.jpg

        第二步、起锅烧油,开大火,油开先放入酸菜和辣椒末,放入大蒜末,反复翻炒,加半碗水烧开;最后放入切碎的鱼香叶快速翻炒,关小火,放调料:花椒面、鸡精/味精、有那么多酸菜千万别放盐别放盐,有香油来点香油,翻炒调味,出锅开干!!!


假鱼香料2.jpg


【原创】 凉拌则儿根
20 06 2020

        今天周六,来一个小时候特别爱得菜,“则儿根”!

        相信则儿根这个菜名很多人都晓得,通过身边朋友了解到,则儿根这个菜“有些人是爱得爱死,有些人是恨得恨死”。我属于前者,从小就吃习惯了,爱到直冒汗,爱到眼泪流,爱到嘘儿呐嘘,爱到有它不吃饭!

        过程:

        第一步、提起撮箕扛上锄头去土头、流水沟儿头挖则儿根、准备细辣椒面(油辣子更香更爽)、花椒面、醋、味精、鸡精、盐、藤椒油。



则耳根5.jpg


第二步、则儿根切短节,搞一个大点的盆子,装上则儿根,放调料:辣椒油、花椒面、藤椒油、醋、味精、盐,醋多一点,个人比较喜欢吃醋,搅拌均匀,开整,爽!!!





        

【原创】 laravel5.6
16 06 2020

PHP框架 - Laravel 5.6

一、composer安装

1.1 composer介绍

composer是php用来管理依赖关系的工具,你可以在自己的项目中申明所依赖的外部关系库,composer会帮你安装这些依赖的库文件;一句话,composer是一个工具,是为php项目准备的软件管家。

1.2 composer工作原理

image.png

1.3 composer安装

windows安装:

命令行安装:

自行去操作...


注意:如果是安装composer.exe文件,一定要安装在使用的版本的php的安装目录,也就是php.exe所在目录

1.4 镜像地址设置:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/   或者  composer config -g repo.packagist composer https://packagist.phpcomposer.com


镜像原理:

image.png


1.5 配置文件修改

①开启php.ini扩展配置:

extension=php_openssl.dll    

extension=php_pdo_mysql.dll  (PDO)

extension=php_mbstring.dll  (mbstring)

extension=php_fileinfo.dll  (验证码)

extension=php_curl.dll       (请求发送)

②开启http.conf配置

LoadModule deflate_module modules/mod_deflate.so

LoadModule rewrite_module modules/mod_rewrite.so

1.6 使用composer更新composer 

composer self-update


二、Laravel安装

2.1 安装具体版本命令:composer create-project laravel/laravel=5.6.* my_laravel --prefer-dist

laravel/laravel=5.6.*   这个* 代表这里安装5.6的最高版本

image.png

image.png

2.2 查看框架版本信息:php  artisan --version

2.3 启动服务:php  artisan serve

2.4 laravel框架目录结构

① 目录文件 省略...

② artisan脚手架文件

注意:使用artisan文件需要注意2点

① php必须添加环境变量,必须保证版本

② artisan必须存在命令行当前的工作路径下,也就是框架的根目录下

2.5 laravel启动方式

①  方式1, 命令启动:php artisan serve  该启动方式不需要启动apache/nginx ,不推荐使用,能跑php,但是不启动数据库

  方式2,  使用wamp环境,配置个虚拟主机


2.6 配置框架app key:php artisan key:generate



三、Laravel基础篇

3.1 路由

① 路由请求方式

get   post   any   put delete  patch  options match ...

//路由匹配方式
Route::match(['get','post'],'hi',function(){
   return 'leigong  nihao!';
});
//路由带参数方式
Route::get('index/{id}',function($id){
   return '编号是'.$id;
});

② CSRF保护

指向 web 路由文件中定义的 POSTPUT 或 DELETE 路由的任何 HTML 表单都应该包含一个 CSRF 令牌字段,否则,这个请求将会被拒绝。

1665816792475910.png


3.2 控制器创建

① 命令方式创建控制器

php artisan make:controller TestController                    默认路径Controllers目录下

php artisan make:controller Admin/AdminController     指定路径,Controllers/Admin目录下

image.png

image.png

② 手动创建控制器

...

③ 通过设置路由访问控制器

Route::访问方式('uri','sction')

Route::get('task','TaskController@index');
Route::get('task/read/{id}','TaskController@read');

④ 接收用户输入

④.① 使用Illuminate\Support\Facades\Input类

image.png

④.② 使用Illuminate\Support\Facades\Request类,静态接收请求参数

image.png

image.png


3.3 路由参数、路由重定向、视图

① 路由参数

①.① 限定路由参数1

//限定路由参数
Route::get('task/read/{id}','TaskController@read')->where('id','[\d]+'); //接收单参数
Route::get('task/more/{id}/{name}','TaskController@more')
   ->where(['id'=>'\d+','name'=>'[a-z]+']); //接收多参数

image.png

①.② 限定路由参数2

image.png


//假设某个id已经在模型绑定器设置为全局,但是在某个方法中又想允许接收参数是任意类型
Route::get('task/read/{qj_id}','TaskController@read')->where('qj_id','.*');

image.png

② 路由重定向

②.① 使用redirect方式

//路由重定向
Route::get('inx','TaskController@index');
Route::get('re','TaskController@re');
//Route::redirect('inx','re');
Route::redirect('inx','http://www.baidu.com/',301);

②.② 使用permanentRedirect方式,可以直接让路由跳转301状态码而不用设置


//不带参数直接301
Route::permanentRedirect('inx','re');

③ 视图路由

③.① 路由形势   Route::view('uri','名称','参数');


//视图路由
Route::view('vi','test.test',['name'=>'leigong']);

image.png

image.png

③.② 使用助手函数


//助手函数方式的路由视图
Route::get('vi2',function(){
  return view('test.test',['name'=>'墨菲特']);
});

③.③ 控制器返回视图

public function vi3(){
   return view('test.test',['name'=>'菲兹']);
}


④ 路由命名

④.①

//路由命名
Route::get('vi3','TaskController@vi3')->name('vvv');

控制器中可以通过助手函数获取url

public function vi3(){
   $url = route('vvv');
   //route('vvv',['id'=>100]);   //route助手函数带参数
   dump($url);
   return view('test.test',['name'=>'菲兹']);
}

④.②

使用redirect()结合route()生成重定向跳转


⑤ 路由分组

路由分组是为了让大量路由共享路由属性,包括中间件、命名空间

⑤.① 路由分组


//路由分组  第一个参数[]如果不写,那当占位符,空分组路由
Route::group([],function(){
  Route::get('vi6',function(){
      return 'vi6';
  });
  Route::get('vi7','TaskController@vi7');
});
//路由分组  第一个参数[]带分组前缀
Route::group(['prefix'=>'pre'],function(){
   Route::get('vi8',function(){
       return 'vi8';
   });
   Route::get('vi9','TaskController@vi7');
});
//推荐路由分组写法
Route::prefix('qa')->group(function(){
   Route::get('qa1',function(){
       return 'qa1';
   });
   Route::get('qa2','TaskController@vi7');
});


⑤.② 可以设置子域名


//可以设置子域名
Route::domain('127.0.0.1')->group(function(){
   Route::get('zyy',function(){
       return '子域名';
   });
});


⑤.③ 可以设置路由路径前缀,通过prefix设置

//路由前缀
Route::prefix('api')->get('vi5','TaskController@vi5');
Route::prefix('api')->get('index',function(){
   return 'index';
});

image.png

⑤.④ 可以指定命名空间


//指定命名空间
Route::namespace('admin')->group(function(){
   Route::get('qa3',function(){
       return 'qa3';
   });
   Route::get('qa4','ManagerController@index');
});



⑥ 单行为、回退、当前路由

⑥.① 单行为控制器 __invoke()方法

使用命令创建:php  artisan make:controller  控制器名称  --invokable


//单行为控制器
Route::get('one','Admin\OneController');  //不用写方法

image.png

⑥.② 路由回退

image.png


//路由回退
Route::fallback(function(){
   return redirect('/');
});

也可以做一个自己的404页面


//自定义404页面
Route::fallback(function(){
   return view('404');
});

image.png

⑥.③ 当前路由信息

//当前路由信息
Route::get('qa5','Admin\ManagerController@qa5');
Route::get('qa6',function(){
   dump(Route::current());
   dump(Route::current()->uri);
});
Route::get('qa7',function(){
   return Route::currentRouteName().PHP_EOL.Route::currentRouteAction();
})->name('qaqa');


⑦ 响应设置和重定向

⑦.① 响应设置

image.png

image.png

image.png

⑦.② 路由重定向

image.png

image.png

image.png

image.png


3.4 资源控制器

① 什么是资源控制器

image.png

创建命令:php artisan make:controller BlogController --resource

image.png

image.png

image.png

image.png

image.png

image.png

①④ 资源路由嵌套

//资源路由嵌套
Route::resource('blogs.comments','Admin\BlogController');   //edit


public function edit($art_id,$comm_id)
{
   return '文章id='.$art_id.PHP_EOL.'评论id='.$comm_id;
}

image.png        

①⑤ 资源浅层嵌套

image.png


3.5 表单伪造和CSRF保护

① 什么是CSRF攻击

image.png

② csrf使用

image.png

注意:有一种情况是没得选择的,只能使用csrf_token,就是使用ajax异步提交表单方式


③ 从csrf中排除列外路由 

image.png


image.png

image.png

image.png

image.png

image.png

image.png

image.png


image.png

image.png



3.6 视图

① 视图文件

image.png

② 加载视图

image.png

③ 变量分配与展示

image.png

image.png

image.png

compact()函数,在当前的符号表中查找该变量名并将它添加到输出的数组中,变量名成为键名而变量的内容成为该键的值!!!

image.png

④ 在模板中使用函数

语法:{{函数名(参数1,参数2)}}

image.png

 循环与分支

image.png

image.png

image.png

 模板继承

image.png

基础页面

image.png

其他子页面

image.png

 模板包含

语法:@include('模板文件名')    文件名不带后缀

image.png

 外部文件引入

image.png



3.7 数据库配置入门

① 数据库配置,本地测试直接配置.env文件

config/database.php文件

② 添加数据

image.png

返回添加数据的id

image.png

③ 取出单行数据

image.png

④ 取出单个指定字段值

image.png

⑤ 查询一些指定字段值

image.png

⑥ 排序

image.png

 分页

image.png


3.8 模型操作

① 理解

每张数据表都对应一个与该表进行交互的“model模型”

image.png

② 使用命令创建模型

php artisan make:model Home/User

image.png

image.png

image.png

③ 模型的使用方式

③.① 模型使用方式一

User::get();   等价于数据库的DB::table('user')->get();

③.② 模型使用方式二    实例化方式

$user = new User();   $user->get();


③.③ 模型添加数据

使用AR模式必须先实例化模型, 添加调用save()方法,返回布尔值

方式1

image.png

方式2

image.png

image.png

image.png

③.④ 查询操作,结果集默认是一个对象

image.png

image.png

image.png

image.png













【原创】 laravel5.6框架
16 06 2020

PHP框架 - Laravel 5.6

一、composer安装

1.1 composer介绍

composer是php用来管理依赖关系的工具,你可以在自己的项目中申明所依赖的外部关系库,composer会帮你安装这些依赖的库文件;一句话,composer是一个工具,是为php项目准备的软件管家。


1.2 composer工作原理

image.png


1.3 composer安装

windows安装:下载Composer-Setup.exe,安装目录选择php对应版本的php.exe所在位置

命令行安装:

php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"


注意:如果是安装composer.exe文件,一定要安装在使用的版本的php的安装目录,也就是php.exe所在目录


1.4 镜像地址设置

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/   或者  composer config -g repo.packagist composer https://packagist.phpcomposer.com


镜像原理:

image.png


1.5 配置文件修改

①开启php.ini扩展配置:

extension=php_openssl.dll    

extension=php_pdo_mysql.dll  (PDO)

extension=php_mbstring.dll  (mbstring)

extension=php_fileinfo.dll  (验证码)

extension=php_curl.dll       (请求发送)

②开启http.conf配置

LoadModule deflate_module modules/mod_deflate.so

LoadModule rewrite_module modules/mod_rewrite.so


1.6 使用composer更新composer 

composer self-update


1.7 使用composer安装项目依赖

composer install :(项目第一次执行composer,没有composer.json文件)


它将会去读取你的composer.lock而非composer.json,并且以此为标准去下载依赖。

当你本地没有composer.lock的时候,它所做的事情和composer update其实并没有区别。

这意味着,只要你本地有一份composer.lock,你就可以保证无论过去了多久,你都能拉到相同的依赖。而如果你把它纳入你的项目的版本控制中,那么你就可以确保你项目中的每一个人、每一台电脑,不管什么系统,都能拉取到一模一样的依赖,以减少潜在的依赖对部署的影响。当然,请记得,你应该使用的命令是composer install。


composer update:(有composer.json文件之后)

当你执行update的时候,composer会去读取composer.json中指定的依赖,去分析他们,并且去拉取符合条件最新版本的依赖。然后他会把所拉取到的依赖放入vendor目录下,并且把所有拉取的依赖的精确版本号写入composer.lock文件中。




二、Laravel框架安装

2.1 安装具体版本命令

composer create-project laravel/laravel=5.6.* my_laravel --prefer-dist

laravel/laravel=5.6.*   这个* 代表这里安装5.6的最高版本

image.png

image.png


2.2 查看框架版本信息:php  artisan --version


2.3 启动服务:php  artisan serve


2.4 laravel框架目录结构

① app目录:项目的核心目录,主要用于存放项目核心代码,也包括控制器、模型

 image.png

image.png

② bootstrap目录:laravel启动目录,引导框架并配置自动加载的文件,该目录还包含了一个 cache 目录,存放着框架生成的用来提升性能的文件,比如路由和服务缓存文件。

③ config目录:项目的配置目录,主要存放项目配置文件

image.png

④ database目录:数据填充和迁移文件

⑤ public目录:项目入口文件和系统静态资源目录(css、js、img)

⑥ resources目录:目录包含了语言包、视图和未编译的资源文件(如 LESS、SASS 或 JavaScript)

⑦ routes目录:目录包含了应用的所有路由定义,Laravel 默认包含了几个路由文件: web.php, api.php, console.php 和 channels.php。

⑧ storage目录:storage 目录包含编译的 Blade 模板、基于文件的会话和文件缓存、以及框架生成的其他文件。这个目录被细分成 app 、 framework 和 logs 三个子目录。 app 目录可以用来存储应用生成的任何文件。 framework 目录用来存储框架生成的文件和缓存。最后, logs 目录包含应用的日志文件。

总结:存放缓存文件和日志文件,在linux系统下,该目录需要有写权限

⑨ vendor目录:主要用于存放第三方类库文件,比如:邮件发送类文件、验证码类文件、laravel框架源码文件等等。

⑩ .env文件:设置系统相关环境信息文件(config目录里面的配置文件内容一般都是读取该文件里面的配置信息)

①① artisan脚手架文件

注意:使用artisan文件需要注意2点

a、 php必须添加环境变量,必须保证版本

b、 artisan必须存在命令行当前的工作路径下,也就是框架的根目录下

①② composer.json:依赖包配置文件

声明当前需要的软件依赖,不能删除,composer需要读取使用


2.5 laravel启动方式

①  方式1, 命令启动:php artisan serve  该启动方式不需要启动apache/nginx ,不推荐使用,能跑php,但是不启动数据库

②  方式2,  使用wamp环境,配置个虚拟主机

image.png


2.6 配置框架app key:php artisan key:generate


三、Laravel入门基础

3.1 laravel路由介绍

a、路由配置文件

image.png

b、路由定义

image.png

image.png

c、请求方式有哪些

image.png

image.png

d、路由参数

image.png

还可以通过?形式get传参:

image.png

image.png

路由别名:

image.png

获取路由列表命令(查看系统已有路由):php artisan route:list

image.png

e、路由群组

image.png

image.png


3.2 控制器使用

a、控制器文件写在哪里

image.png

b、控制器命名

大驼峰命名 + Controller.php

c、创建控制器

php artisan make:controller TestController                    默认路径Controllers目录下

php artisan make:controller Admin/AdminController     指定路径,Controllers/Admin目录下

image.png

image.png

image.png

d、控制器路由

image.png

image.png

e、接收用户输入

① 使用Illuminate\Support\Facades\Input类,Input静态接收请求参数

image.png

image.png

image.png

Facades:门面思想。门面是一个介于类的实例化与没有实例化中间的一个状态,其实是类的一个接口实现。这个状态下可以不实例化类,但是可以调用类中的方法。说白了就是静态方法。

在laravel中如果需要使用facades,但又不想写那么长的引入操作,则可以在config/app.php中定义长串的别名(aliases数组中定义别名)。

image.png

② 使用 Illuminate\Http\Request类,Request依赖注入的方式获取输入参数

image.png

image.png

③ 使用Illuminate\Support\Facades\Request类,Request静态接收请求参数

image.png

image.png


3.3 DB类操作数据库

a、引入DB类文件

image.png

注意:使用DB类,需要use  Illuminate\Support\Facades\DB类,DB门面类在app.php文件中已经定义了别名DB,可以直接use DB,不需要写太长的空间

image.png

b、新增数据

image.png

image.png

c、修改数据

image.png

image.png

d、查寻数据

image.png

//获取数据
public function getData(){
   
//1.获取所有数据
   
$db = DB::table('user');
   
$data1 = $db->get();
   
//var_dump($data1);
   
foreach ($data1 as $k=>$v){
       
//get查寻出来都是对象,不能再用访问数组的方式访问,必须访问对象方式访问数据
       
var_dump($v->name);
   
}
   
//2.大于...
   
$data2 = DB::table('user')->where('id','>',2)->get();
   
dump($data2);
   
//3.获取单行或列
   
$one = DB::table('user')->first(); //返回一个对象,相当于limit(1)
   //$one = $db->where('name','
菲兹')->first();
   
dump($one);
   
//4.获取某个具体的值
   
$data3 = DB::table('user')->where('id','=',3)->value('email');
   
dump($data3);
   
//5.获取某些字段的值
   
$data4 = DB::table('user')->select('name','age','email')->get();
   
dump($data4);
   
//6.分块查寻
   
echo '<hr/>';
   
DB::table('user')->orderBy('id')->chunk(1,function($user){
       
foreach ($user as $k=>$v){
           dump(
$v);
       
}
   })
;
}

e、排序操作

public function paixu(){
   
$db = DB::table('user');
   
$data1 = $db->orderBy('id','desc')->get();
   
dump($data1);
}

f、分页操作

public function fenye(){
   
$db = DB::table('user');
   
//limit:限制输出的条数
   
//offset:从什么地方开始
   
//组合起来等价于  limit 2,1
   
$data1 = $db->limit(2)->offset(1)->get();
   
dump($data1);
}

g、删除操作

image.png

public function delete(){
   
$db = DB::table('user');
   
$data1 = $db->where('id','<',3)->delete();
   
dd($data1); //返回删除数据的条数
}

h、执行任意的sql语句

image.png

public function doSql(){
   
//1.statement语句
   
$data1 = DB::statement("insert into user values(6,'卡莎',18,'kasha@163.com')");
   
var_dump($data1);
   
//2.select语句
   
$data2 = DB::select("select * from user");
   
dump($data2);
}



3.4 视图操作

a、视图写在哪里

视图可以进行分目录管理的

image.png

b、视图文件的命名与渲染

image.png

image.png

image.png

c、变量的分配与展示

image.png

public function assignVar(){
   
$date = date('Y-m-d H:i:s',time());
   
$day = '星期六';
   
//return view('article.list',['date'=>$date,'day'=>$day]);
   
return view('article.list')->with(['date'=>$date,'day'=>$day]);
}

d、compact()函数使用

compact函数使php内置函数,跟框架没有关系,主要作用用于打包数组,在当前的符号表中查找该变量名并将它添加到输出的数组中,变量名成为键名而变量的内容成为该键的值!!!

语法:compact('变量名1','变量名2',...)

image.png

e、在模板视图中使用函数

image.png

语法:{{函数名(参数1,参数2)}}

说明:函数可以是php内置的函数,也可以是laravel框架中定义的

image.png

f、循环与分支

image.png

image.png

image.png

g、模板继承

image.png

父级页面:

image.png

子级页面:

image.png

h、文件包含

语法:@include('模板文件名')    文件名不带后缀

image.png

i、外部文件引入

在laravel框架中,封装了一个asset()方法

image.png

注意:href = "{{asset('css/blog/')}}"  asset()方法的参数可以是单级目录,也可以是多级目录


3.5 CSRF攻击

a、什么是csrf攻击

image.png

b、csrf使用

image.png

image.png

image.png

image.png

注意:有一种情况是没得选择的,只能使用csrf_token,就是使用ajax异步提交表单方式

区别:csrf_token只是输出了token值,csrf_field输出了整个input隐藏域

c、csrf验证中排除列外路由

image.png

image.png

action地址写法一:

image.png

image.png

action地址写法二:

image.png

image.png



3.6 模型操作(AR模式)

a、模型介绍

image.png

b、模型文件位置和模型文件创建

image.png

使用命令创建模型:php artisan make:model Admin\Article

image.png

image.png

c、定义模型

image.png

//定义模型关联的数据表
protected $table = 'user';
//定义主键
protected $primaryKey = 'id';
//定义禁止操作时间
public $timestamps = false;  //数据表中没有created_at updated_at字段时必须禁用!!!
//设置允许写入的字段,使用create()方法的时候必须定义$fillable属性
protected $fillable = ['name','age','email'];
//设置不允许写入字段, $fillable $guarded 只能二选一设置
//protected $guarded = ['price'];


d、在控制器中使用模型

use App\Admin\User;                     //在控制器中操作模型,use模型

方式①:AR模式

实例化模型,然后再去使用类,例如:  $model = new User();   $model->get();

image.png

public function userAdd1(){
   //1.实例化模型
   $userModel = new User;      //dd($userModel);
   //2.给属性赋值,字段与类的属性映射
   $userModel->name = Input::get('name');
   $userModel->age = Input::get('age');
   $userModel->email = Input::get('email');
   $res = $userModel->save();
   dd($res); //这种方式返回 bool 类型结果
}

注意:上面这种方法可以完成数据的插入,但是开发中不建议使用

方式②:

直接像使用DB门面一样的的操作,以调用静态方法为主的形式,该形势下模型不需要实例化,例如: User::get();  等价于  DB::table('user')->get();  

image.png

public function addForm(){
   //1.加载静态页面视图
   return view('admin.user.useradd2');
}
public function userAdd2(Request $request){
   //2.使用User::create()方式写入数据,依赖注入的方式接收变量
   $res = User::create($request->all());
   //$data = Input::all();
   //var_dump($data);
   dd($res);  //这种方式返回 obj 类型结果
}


注意:如果使用create()方法,则需要在模型中定义fillable属性 允许写入的字段,如果数据表中没有时间相关字段也需要禁用时间自动更新功能

e、查询操作

public function userList(){
   //1.查寻单条指定id的数据
   $res = User::find(9); //返回 obj
   dump($res);
   dump('姓名:'.$res->name.' 年龄:'.$res->age);
   //2.查寻所有数据转成数组
   $res3 = User::get()->toArray();
   dump($res3);
   //3.查寻符合条件的第一条数据
   $res4 = User::where('id','>',6)->first()->toArray();
   var_dump($res4);
   //4.all()方法
   $res5 = User::all(); //all()方法查询,不支持链接其他辅助查寻方法
   dump($res5);
   //5.get()方法获取某些字段
   $res5 = User::where('id','>',12)->get(['id','name'])->toArray();
   var_dump($res5);
   echo '<br>';
   //6.select()获取某些字段
   $res6 = User::where('id','>',10)->select('id','name','age')->get()->toArray();
   dump($res6);
}

f、修改数据

image.png

public function userEdit(){
   //1.AR模式修改操作
   $data = User::find(6);
   dump($data); //obj
   //给要修改的字段赋值
   $data->email = 'aike@163.com';
   //保存修改
   $res1 = $data->save();
   dump($res1);

   //2.模型使用update方式更新数据
   $res2 = User::where('id',6)->update(['email'=>'aike2@163.com']);
   dump($res2);   //int 1|0
}

g、删除数据

image.png

public function userDelete(){
   //1.模型删除操作
   $data = User::find(10);
   $res1 = $data->delete();
   var_dump($res1);   //返回bool true|false

   //2.DB类里面的方式删除
   $res2 = User::where('id','>',14)->delete();
   var_dump($res2); //int 返回受影响的行数
}



3.7 自动验证

a、自动验证介绍

image.png

b、演示浏览器禁用js功能

未禁用之前:

image.png

设置浏览器禁用js:

image.png

禁用以后:

image.png

image.png

注意:所以一个功能完善的应用,前后端都要做验证,不止单独的前端或者单独的后端单方面做验证!!!

c、获取/判断请求方式

public function userAdd3(Request $request){
   //1.请求方式判断一
   $method1 = $request->isMethod('POST');  //true
   var_dump($method1);
   //2.请求方式判断二
   $method2 = request()->method();     //POST
   var_dump($method2);
   //3.请求方式判断三
   $method3 = Input::method();         //POST
   var_dump($method3);
   //4.请求方式判断四
   $method4 = Request::METHOD_POST;    //POST
   var_dump($method4);
   $method5 = FacRequest::method();    //POST 静态Request的别名 FacRequest
   var_dump($method5);
}


d、快速验证($this->validate验证)

image.png

注意:多个验证规则使用 "|" 字符进行隔开

语法:$this->validate(数据对象,数组形式的验证规则)


image.png

//1. 快速验证($this->>validate验证)
public function addForm3(){
   //1.加载静态页面视图
   return view('admin.user.useradd3');
}
public function uValidate(Request $request){
   //使用场景,返回到模板中
   if(Request::METHOD_POST == 'POST'){
       $input = $this->validate($request,[
           //验证规则
           'name'  =>  'required|between:2,10|alpha_dash',
           'age'   =>  'required|integer|between:18,100',
           'email' =>  'required|email|unique:user,email',
           'tel'   =>  'required',
       ],[
           'name.required' =>  '姓名必须填写',
           'name.between' =>  '姓名2-10个字符',
           'name.alpha_dash' =>  '姓名只能是字母、数字、破折号( - )以及下划线( _ ',
           'age.required' =>  '年龄必须填写',
           'age.integer' =>  '年龄请填写整数',
           'age.between' =>  '年龄18-100岁之间',
           'email.required' =>  '邮箱必须填写',
           'email.email' =>  '邮箱格式不对',
           'email.unique' =>  '邮箱已经存在',
           'tel.required'  =>  '手机号必须填写',
       ],[
           'name'  =>  '姓名',
           'age'   =>  '年龄',
           'email' =>  '邮箱',
           'tel'   =>  '手机号',
       ]);
       return ['msg'=>$input];
   }else{
       return ['code'=>100501,'msg'=>'请求方式错误'];
   }
}


image.png

<body>
<form action="{{route('ad3')}}" method="post">
   姓名:<input type="text" name="name" id=""><br/>
   年龄:<input type="text" name="age" id=""><br/>
   邮箱:<input type="text" name="email" id=""><br/>
   <input type="hidden" name="_token" value="{{csrf_token()}}">
   <input type="submit" value="提交">
</form>
@if ($errors->any())
   <div class="alert alert-danger">
       <ul>
           @foreach ($errors->all() as $error)
               <li>{{ $error }}</li>
           @endforeach
       </ul>
   </div>
@endif
</body>

响应效果:

image.png


e、独立验证

use Validator;
//2.独立验证
public function addForm5(){
   //1.加载静态页面视图
   return view('admin.user.useradd5');
}
public function duliValidate(Request $request){
   //使用场景,响应ajax
   if($request->isMethod('POST')){
       $validator = Validator::make($request->all(),[
           'name'  =>  'required|between:2,10|alpha_dash',
           'age'   =>  'required|integer|between:18,100',
           'email' =>  'required|email|unique:user,email',
           'tel'   =>  'required',
       ],[
           'name.required' =>  '姓名必须填写',
           'name.between' =>  '姓名2-10个字符',
           'name.alpha_dash' =>  '姓名只能是字母、数字、破折号( - )以及下划线( _ ',
           'age.required' =>  '年龄必须填写',
           'age.integer' =>  '年龄请填写整数',
           'age.between' =>  '年龄18-100岁之间',
           'email.required' =>  '邮箱必须填写',
           'email.email' =>  '邮箱格式不对',
           'email.unique' =>  '邮箱已经存在',
           'tel.required'  =>  '手机号必须填写',
       ],[
           'name'  =>  '姓名',
           'age'   =>  '年龄',
           'email' =>  '邮箱',
           'tel'   =>  '手机号',
       ]);
       //dump($validator);
       //dump(get_class_methods($validator)); //获取类里面的所有方法
       //如果有错误,返回true
       if($validator->fails()){
           return redirect()->back()->withErrors($validator);
       }
   }else{
       return ['code'=>100501,'msg'=>'请求方式错误'];
   }
}


f、表单验证(验证器验证)

创建表单验证类文件: php artisan make:request Admin/ArticleRequest

image.png


namespace App\Http\Requests\Admin;
//单个验证规则失败后停止验证所有规则
protected $stopOnFirstFailure = true;
/**
* 如果您打算在应用程序的其它部分处理请求的授权逻辑,只需从 authorize 方法返回 true
* @return bool
*/
public function authorize()
{
   return true;  //设置为true
}

/**
* 书写验证规则
* @return array
*/
public function rules()
{
   return [
       'name'  =>  'required|between:2,10|alpha_dash',
       'age'   =>  'required|integer|min:18|max:100',
       'email' =>  'email|unique:user,email',
       'tel'   =>  [
           'required',
           'unique:user,tel',
           'regex:/^1[3456789][\d]{9}$/'
       ],
       'pwd'   =>  'required|alpha_dash|between:6,16|confirmed', //confirmed属性写在原始密码字段上
       //'pwd_confirmation'  =>  'required|alpha_dash|same:pwd', //same,验证字段必须与给定字段匹配
       'pwd_confirmation'  =>  'required|alpha_dash',  //same 和 原始密码字段的confirmed有一个就行
       'pic'   =>  'nullable|image|max:100',   //laravel5.6bug,需要去修改允许上传的文件格式!!!
       //'pic'   =>  'mimes:jpg,jpeg,png,gif,bmp,webp|max:100',
   ];
}

//自定义错误信息
public function messages()
{
   return [
       'name.required' =>  '姓名必须填写',
       'name.between' =>  '姓名2-10个字符',
       'name.alpha_dash' =>  '姓名只能是字母、数字、破折号( - )以及下划线( _ )组成',
       'age.required' =>  '年龄必须填写',
       'age.integer' =>  '年龄请填写整数',
       'age.min' =>  '必须年满18',
       'age.max' =>  '年龄不超过100',
       //'email.required' =>  '邮箱必须填写',
       'email.email' =>  '邮箱格式不对',
       'email.unique' =>  '邮箱已经存在',
       'tel.required'  =>  '电话号码必须填写',
       'tel.unique'  =>  '电话号码已经存在',
       'tel.regex'  =>  '电话号码不正确',
       'pwd.required' => '密码不能为空',
       'pwd.between' => '密码6-16位字符',
       'pwd.alpha_dash' => '密码只能是字母、数字、破折号( - )以及下划线( _ )组成',
       'pwd_confirmation.required' => '确认密码不能为空',
       'pwd_confirmation.alpha_dash' => '确认密码只能是字母、数字、破折号( - )以及下划线( _ )组成',
       'pwd.confirmed' => '两次密码不一致',
       //'pic.mimes' =>  '请上传jpeg,bmp,png,gif,jpg格式图片',
       'pic.image' =>  '请上传jpg,jpeg,bmp,png,gif,webp格式图片',
       'pic.max'   =>  '上传图片大小不超过100kb',
   ];
}


use App\Http\Requests\Admin\User as UserValidate; //自定义表单验证
public function addForm4(){
   //1.加载静态页面视图
   return view('admin.user.useradd4');
}
//进行表单验证
public function zdyValidate(UserValidate $request){
   //获取通过验证的数据
   $valited = $request->validated();
   //dump($valited); //array
   //获取部分通过验证的数据
   //$valited2 = $request->safe()->only(['name','email']);
   //dd($valited2);
   //调用写入数据库方法
   $res = self::userAdd4($request);
   if($res){
       $data = ['code'=>100016,'msg'=>'添加成功'];
       //设置setEncodingOptions(JSON_UNESCAPED_UNICODE),返回数据禁止Unicode编码
       //return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);
       return response()->json($data);
   }else{
       $data = ['code'=>100015,'msg'=>'添加失败'];
       return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);
   }
}

public function userAdd4(Request $request){
   $salt = getRandomString($length = 15);  //获取盐str
   //密码加密
   //$pass1 = Crypt::encrypt($request->input('pwd'));              //一长串,188个字符
   $pass = Hash::make($request->input('pwd').$salt);    //60个字符
   $data = $request->except(['pwd','pwd_confirmation']);
   $data['pwd'] = $pass;
   $data['salt'] = $salt;
   return UserModel::create($data);
}


g、输出效果展示成中文:

image.png

① 语言包下载网址:https://packagist.org/,搜索laravel-lang,选择下载量最多、收藏最多的下载

image.png

② 下载包:

image.png

③ 查看文档:

image.png

image.png

④ laravel5-语言包安装命令:

在项目根目录下面执行语言包安装命令   composer require laravel-lang/lang:^3.0      或者   composer require laravel-lang/lang:^3.0 laravel-lang/publisher:^3.0

下载原始包文件位置:

image.png

⑤ 复制zh-CN文件夹到框架如下目录:

image.png

⑥ 修改laravel框架配置文件:config/app.php,修改 'locale'  => 'en'   为  'locale'  => 'zh-CN' 

image.png

⑦ 测试效果

image.png

⑧ 修改语言包中错误,resources/lang/validation.php 中age字段,  'age' =>'年轻'  改为   'age' => '年龄'

image.png

⑨ 语言包中添加字段 ,resources/lang/validation.php 中添加tel字段测试

image.png

image.png


h、修改laravel框架返回数据,禁止Unicode编码

① return json数据的地方加上setEncodingOptions(JSON_UNESCAPED_UNICODE)

return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);

② 修改文件: vendor\laravel\framework\src\Illuminate\Http\JsonResponse.php的构造函数,$this->encodingOptions = $options ;  修改为  $this->encodingOptions = JSON_UNESCAPED_UNICODE ;

public function __construct($data = null, $status = 200, $headers = [], $options = 0)
{
   //$this->encodingOptions = $options;
   $this->encodingOptions = JSON_UNESCAPED_UNICODE;

   parent::__construct($data, $status, $headers);
}


i、laravel框架中添加公共函数

① 在app目录下面新建Helper\functions.php文件

image.png

② 配置composer

打开根目录下的composer,在autoload项下面按照图示配置

image.png

 执行composer命令

 composer dump-auto

image.png



3.8 文件上传

a、表单方式上传

不考虑异步(js、ajax)上传,使用纯表单提交上传,需要注意点有以下:

① 表单type="file"   ,提交方式 method 为post  

② form表单具有enctype="multipart/form-data" 属性

multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思 ;默认情况下,enctype的值是application/x-www-form-urlencoded,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据。 

③ 具备一个提交按钮,submit可以直接提交,  button需要写js提交

注意:文件上传的核心 就是文件移动,move_upload_file()


b、超全局变量$_FILES 

image.png

c、处理上传文件

image.png

//3.8 文件上传
//加载静态页面
public function fileView(){
   return view('admin.user.files');
}
//处理文件上传
public function fileUpload(Request $request){
   if($request->isMethod('POST')){
       $file = $request->file('pic');
       //$pic = $request->pic;  两个获取结果一样,都是Illuminate\Http\UploadedFile对象

       //判断是否有上传文件 且 上传的文件是否有效
       if($request->hasFile('pic') && $request->file('pic')->isValid()){
           //获取文件的原始名称
           dump($request->file('pic')->getClientOriginalName());
           //获取文件扩展名
           dump($request->file('pic')->getExtension());
           //获取文件上传错误码,上传成功为0
           dump($request->file('pic')->getError());
           //获取文件原始后缀名
           dump($request->file('pic')->getClientOriginalExtension());
           //获取文件mime类型
           dump($request->file('pic')->getClientMimeType());
           //获取文件上传的错误信息
           dump($request->file('pic')->getErrorMessage());


           //移动文件
           $path = './uploads/avatar/'.date('Ymd',time());
           $fileName = md5(time().rand(100000,999999)).'.'.$request->file('pic')->getClientOriginalExtension();
           //返回 Symfony\Component\HttpFoundation\File\File 对象
           $request->file('pic')->move($path,$fileName);
           $data = $request->all();
           $data['pic'] = date('Ymd',time()).'/'.$fileName;
           //添加到数据库
           UserModel::create($data);
       }else{
           $data = ['code'=>100012,'msg'=>'上传失败'];
           return response()->json($data);
       }
   }else{
       $data = ['code'=>100010,'msg'=>'请求方式错误'];
       return response()->json($data);
   }
}


d、laravel5.6框架图片验证bug修改

① 原因:上传jpeg、jpg后缀图片,提示请上传图片文件; png、gif后缀的图片文件能够验证通过

② 添加允许上传的文件后缀

a、找到文件位置:D:\xxx\la56\vendor\laravel\framework\src\Illuminate\Validation\Concerns

b、找到文件名:ValidatesAttributes.php

c、找到validateImage()方法,添加允许上传的文件格式

public function validateImage($attribute, $value)
{
   return $this->validateMimes($attribute, $value, ['jpg','jpeg', 'png', 'gif', 'bmp', 'svg','webp']);
}

注意:多文件上传验证规则

image.png

image.png


e、封装一个文件上传函数

use Illuminate\Http\Request;
/**
* 多文件上传
* @param Request $request      *请求对象
* @param $fieldName            *表单字段名称
* @param $category             *保存文件的分类文件夹名称
* @return array|\Illuminate\Http\JsonResponse
*/
function multiFileUpload($request,$fieldName = null,$category = null){
   //$request->file($fieldName) array[obj] ,多图片上传的时候数据结构:数组里面是文件对象
   if($request->hasFile($fieldName) && $request->file($fieldName)){
       $result = [];
       foreach($request->file($fieldName) as $file){
           //移动文件
           $path = './uploads/'.$category.'/'.date('Ymd',time());
           $fileName = md5(time().rand(100000,999999)).'.'.$file->getClientOriginalExtension();
           $file->move($path,$fileName);
           $result[] = date('Ymd',time()).'/'.$fileName; //20190128/8df7306be.jpg
       }
       return $result;
   }
}


3.9 数据分页

a、laravel分页简介

在laravel里面完成分页是很简单的,它的思想和其他框架有些不一样,其他一些框架使用的分页类完成的,laravel是直接调用模型的分页方法,返回对应的数据和分页字符串


b、分页类文件位置

image.png


c、模型用法

image.png

语法:{{$保存数据的对象->links()}} 


public function paginate(){
   //1. 没有分页的效果
   $data1 = UserModel::select('id','name','age','email','tel','pic')->orderBy('id','desc')->get();
   //2.简单分页效果
   $data2 = UserModel::select('id','name','age','email','tel','pic')->orderBy('id','desc')->simplePaginate(10);
   //3.分页效果
   $data3 = UserModel::select('id','name','age','email','tel','pic')->orderBy('id','desc')->paginate(15);
   foreach($data3 as $k=>$v){
       $data3[$k]['pic'] = '/uploads/avatar/'.$v['pic'];
   }
   return view('admin.user.paginate',compact('data3'));
}

image.png

① 简单分页效果

image.png

② 普通分页效果

image.png


d、自定义分页视图效果

自定义分页视图的制作最简单的方法是使用 vendor:publish 命令将它们导出到 resources/views/vendor 目录:

使用命令php artisan vendor:publish --tag=laravel-pagination  移动文件

编辑default.blade.php 和 bootstrap-4.blade.php 文件修改显示效果

image.png


3.10 验证码

a、安装验证码依赖包

网址:https://packagist.org/

包名:搜索  captcha 

image.png

指定版本安装:composer require mews/captcha=3.0.2     这里安装mews/captcha  3.0.2版本

image.png


b、修改配置文件

config/app.php文件配置

① 注册提供商

//验证码服务提供者
Mews\Captcha\CaptchaServiceProvider::class,

② 配置aliases 键

'Captcha' => Mews\Captcha\Facades\Captcha::class,


c、自定义参数配置

使用命令生成配置文件:php artisan vendor:publish

image.png

image.png


'default' => [
   'length' => 5,
   'width' => 120,
   'height' => 36,
   'quality' => 90,
   'math' => true,
   //'expire' => 60,
],


d、实现验证码显示

返回URL:captcha_src()      返回图片:captcha()       返回HTML:captcha_img()

<img src="{{captcha_src()}}" alt="验证码" onclick="this.src=this.src+'?'+Math.random()">


e、验证码验证

'code'   =>  'required|captcha',
'code.required'  =>  '验证码不能为空',
'code.captcha'  =>  '验证码不正确',

image.png

image.png


3.11 数据表的迁移与填充


1、数据的迁移操作

a、介绍

迁移:创建数据表的操作 + 删除数据表的操作

填充:往数据表里面填充写入数据(数据的插入操作)


b、数据的迁移操作

在迁移过程中,操作可以分为两个部分:创建与编写迁移文件    执行迁移文件

迁移文件默认位置:

image.png

① 创建迁移文件

案例:创建一张表,假设数据表的名字叫做paper,迁移文件名:create_paper_table

创建的时候可以通过artisan命令来执行迁移文件的生成:php artisan make:migration 迁移文件名

/**
* Run the migrations.
*创建数据表
* @return void
*/
public function up()
{
   Schema::create('paper', function (Blueprint $table) {
       $table->increments('id');
       $table->timestamps();
   });
}

/**
* Reverse the migrations.
*删除数据表
* @return void
*/
public function down()
{
   Schema::dropIfExists('paper');
}


② 编写迁移文件代码

编写迁移代码,实现数据表的up方法和down方法,参考框架database\migrations\目录下原始的文件书写

案例要求:

image.png

$table表示整个表的实例,语法:$table->列类型方法('字段名',[长度/值范围])->列修饰方法();


public function up()
{
   Schema::create('paper', function (Blueprint $table) {
       $table->increments('id');
       $table->string('paper_name',100)->notNull()->unique();
       $table->tinyInteger('total_score',tinyint)->default(100);
       $table->integer('start_time')->nullable();
       $table->integer('duration');
       $table->tinyInteger('status')->default(1);
       $table->timestamps();
   });
}
public function down()
{
   Schema::dropIfExists('paper');
}


c、执行迁移文件

① 执行up方法(创建数据表)

image.png

第一次执行迁移文件,需要执行的命令:php artisan migrate:install   生成一张migrations表,如下:

image.png

执行命令:php artisan migrate     【执行迁移文件的,创建数据表】

image.png


② 执行down方法(删除数据表)

执行命令:php artisan migrate:rollback     【回滚最后一次的迁移操作,不会删除迁移文件】

image.png

image.png


注意:迁移文件的文件名不要做任何修改,要报错!!!

image.png



2、数据表填充器

填充操作就是往数据表中写测试数据的操作

a、填充器所在目录

image.png


b、创建填充器

使用命令:php artisan make:seeder      【建议写法:大写表名+TableSeeder】  如:PaperTableSeeder


class PaperTableSeeder extends Seeder
{
   public function run()
   {
       //
   }
}



c、编写填充器代码

注意:在填充器文件中可以使用DB门面去新增数据,但是需要注意,DB门面在使用的时候不需要用户再去引入,一旦引入则报错,可以直接使用

public function run()
{
   DB::table('paper')->insert([
       'paper_name'    => '07年中考',
       'total_score'   => 558,
       'start_time'    => strtotime('+7 days'),
       'duration'      => 120,
       'status'        => 1
   ], [
           'paper_name'    => '13年高考',
           'total_score'   => 556,
           'start_time'    => strtotime('+7 days'),
           'duration'      => 120,
           'status'        => 1
       ]
   );
}


d、执行填充器文件

使用命令:php artisan db:seed --class = 需要执行的种子文件名

php artisan db:seed --class=PaperTableSeeder

image.png

image.png



3.12 响应处理

在laravel框架中响应正常的情况有两种, 一是常规的直接响应,另外一个是ajax响应;其中展示视图和直接响应字符串都属于常规响应


1、 常规响应

return view('admin.user.lis');

return 'hello';


2、 ajax响应

① 常见的ajax响应数据类型

json、xml、text/html

image.png

案例:

image.png

a、发送请求

image.png


b、响应处理


//处理响应处理
public function ajaxResponse(Request $request){
   if($request->isMethod('GET')){
       $data = UserModel::get();
       return response()->json($data); //响应给laravel框架的必须是字符串or对象
       //return ['a'=>10,'b'=>100];  //转成obj
   }else{
       $data = ['code'=>100010,'msg'=>'请求方式错误'];
       return response()->json($data);
   }
}


② 跳转响应(重定向)

语法:

return redirect('路由');

return redirect()->to('路由');



3.13 会话控制(记忆)

session默认存到文件中,session文件的目录:storage/framework/sessions

① 使用session

控制器中引用 use Illuminate\Support\Facades\Session,  由于session门面在app.php中已经定义好了别名,所以在控制器中可以直接use  Session;

image.png

public function huihua(){
   //1. 存储一个变量
   Session::put('name','红家伙');
   Session::put('age','19');
   session_start();
   dump($_SESSION);  //这里原生获取不到
   //2. 获取一个变量
   echo Session::get('name').'<br>';
   //3.获取一个默认值
   echo Session::get('name2','那个.').'<br>';
   echo Session::get('name6',function(){
       return '就是她';
       }).'<br>';
   //4.获取所有session信息
   dump(Session::all());
   //5.检查某个session是否存在
   dump(Session::has('name'));
   //6. 删除一个session变量
   dump(Session::forget('name'));
   //删除session中全部变量
   Session::flush();
   dump(Session::all());
}



3.14 缓存操作

laravel为不同的缓存提供了统一的API,缓存配置位于config/cache.php。在该文件中指定使用哪个缓存,系统默认使用文件缓存,其缓存位置位于:storage/framework/cache/data

① 设置缓存

image.png


② 获取缓存

image.png


③ 删除缓存数据

image.png

④ 缓存数值的增加/减少

image.png

⑤ 获取并存储

image.png

image.png

public function huancun(){
   //1.设置一个缓存,如果存在,则覆盖
   Cache::put('name','那个人',100);
   //2.设置一个缓存,存在同名则不添加
   Cache::add('age','20',50);
   Cache::add('mimi','200',1000000);
   //3.永久存储
   Cache::forever('sex','');
   //4.获取值
   $value1 = Cache::get('name');
   dump($value1);
   //4.获取值,不存在则使用默认值
   $value2 = Cache::get('sign',function(){
       return '这个家伙很懒,什么都没留下';
   });
   dump($value2);
   //5.检查缓存中是否存在某个值
   if(Cache::has('sex')){
       echo '存在值';
   }else{
       echo '不存在值';
   }
   //6.从缓存中获取缓存,然后删除
   $value3 = Cache::pull('sex');
   dump($value3);
   dump(Cache::get('sex'));
   //7.从缓存中移出缓存数据
   $value4 = Cache::forget('age');
   dump($value4); dump(Cache::get('age'));
   //8.清除所有缓存,并且删除目录
   //Cache::flush();
   //9.缓存值增加/减少
   Cache::increment('mimi',10);
   Cache::decrement('mimi');
   //10.设置一个默认时间
   $time = Cache::remember('time',100,function(){
       return date('Y-m-d H:i:s',time());
   });
   dump($time);
   //11.永久存储
   $day = Cache::rememberForever('timeforever',function(){
       return date('Y-m-d',time());
   });
   dump($day);
}



3.15 中间件

中间件作为请求和响应的中间人,它是一种过滤机制类型。在laravel中通过中间件来进行后台用户是否登录的验证操作,防止后台用户翻墙操作。

image.png

a、创建中间件

php artisan make:middleware  中间件名


b、中间件所在目录

image.png

image.png


c、注册中间件

在laravel中,中间件有两种类型; 即全局中间件(不管是在前台还是在后台都执行)和路由中间件。全局中间件将在应用程序的每个HTTP请求运行,而路由中间件将被分配到一个特定的路由,中间件可在  模app\Http\Kernel.php 注册

该文件包含两个属性,$middleware 和 $routeMiddleware, $middleware属性用于注册全局中间件, $routeMiddleware用于注册路由指定中间件。

① 全局中间件

image.png

image.png

image.png


② 路由中间件 (直接路由中间件、路由分组中间件)

image.png

路由web.php中注册路由中间件

image.png

image.png


③ 特殊的一种,控制器中间件

image.png



3.16 联表查询

① 普通联表查询

数据来源:文章表、作者表

表1:文章表      t1    主表(跟在from关键词后面的表)

表2:作者表      t2    从表(跟在join关键词后面的表)

关联条件:文章表的author_id = 作者表的id

联表方式:左外连接

原始sql:select t1.id,t1.article_name,t2.author_name from article as t1 left join author as t2 on t1.author_id=t2.id;


public function lianbiao(){
   $data = DB::table('article as t1')
       ->select('t1.id','t1.article_name','t2.author_name')
       ->leftJoin('author as t2','t1.author_id','=','t2.id')
       ->get();
   dump($data);
}



3.17 模型关联

① 一对一关联关系

例如:一篇文章只有一个作者

a、创建模型

image.png

b、定义模型代码


class Article extends Model
{
   //定义模型关联的数据表
   protected $table = 'article';
   //定义主键
   protected $primaryKey = 'id';
   //定义禁止操作时间
   public $timestamps = false;
}


class Author extends Model
{
   //定义模型关联的数据表
   protected $table = 'author';
   //定义主键
   protected $primaryKey = 'id';
   //定义禁止操作时间
   public $timestamps = false;
}


c、关联模型的关联方法

注意:在写关联模型的时候要分析出谁关联谁,谁做主动关联的模型。 当前案例:文章关联作者,文章是主模型,需要关联代码写在主模型中

//模型关联操作:关联作者模型(一对一)
//语法
public function 被关联的模型名小写(){
   return $this->hasOne('需要关联模型的命名空间','被关联模型的关系字段','本模型中的关系字段');
}

public function author(){
   return $this->hasOne('App\Admin\Author','id','author_id');
}

关联关系的使用方法:使用动态属性进行调用

image.png

案例:通过模型关联的一对一关系查询出每篇文章对应的作者名称


//1.一对一
public function oneOnOne(){
   $data = \App\Admin\Article::get(); //$data  Illuminate\Database\Eloquent\Collection 对象
   foreach($data as $key=>$value){    //$value Article模型对象
       echo '文章编号是:'.$value->id.';&emsp;'.'文章名称是:'.$value->article_name.';&emsp;'.'文章作者是:
       '.$value->author->author_name.'<br>';
   }
}


image.png

注意:使用模型一对一关联关系之后,其可以替代之前写的join联表操作



一对多关联关系

例如:一篇文章有多条评论

a、创建评论表:

image.png

b、创建评论模型:

class Comment extends Model
{
   //定义模型关联的数据表
   protected $table = 'comment';
   //定义主键
   protected $primaryKey = 'id';
   //定义禁止操作时间
   public $timestamps = false;
}

c、关联模型的关联方法:文章模型(主) 、评论模型(从)

需求:查询出每篇文章下所有的评论


//语法
public function 被关联的模型名小写(){
   return $this->hasMany('需要关联模型的命名空间','被关联模型的关系字段','本模型中的关系字段');
}
public function comment(){
   return $this->hasMany('App\Admin\Comment','art_id','id');
}


//2.一对多
public function oneToMore(){
   //查询数据
   $data = \App\Admin\Article::get();          //$data  Illuminate\Database\Eloquent\Collection 对象
   foreach ($data as $key=>$value){            //$value App\Admin\Article模型对象
       echo '文章编号:'.$value->id.';&emsp;'.'文章名称是:'.$value->article_name.';&emsp;'.'其下评论有:<br>';
       //$value->comment 这里的comment是模型里面的方法!!!
       foreach ($value->comment as $k=>$v){    //$v     App\Admin\Comment 模型对象
           echo '&emsp;'.$v->comment.'<br>';   //comment是字段!!!
       }
   }
}

效果:

image.png



③ 多对多关联关系

例如:一篇文章可能有多个关键词,一个关键词可能被多篇文章使用

image.png


a、建表:已经存在文章表,还需要关键词表、关键词和文章的关系表

image.png

image.png


b、创建模型:

注意:根据手册中记录的语法要求,不需要给关系表单独的创建模型


class Keyword extends Model
{
   //定义模型关联的数据表
   protected $table = 'keyword';
   //定义主键
   protected $primaryKey = 'id';
   //定义禁止操作时间
   public $timestamps = false;
}



c、查询每篇文章下的关键词

//语法
public function 被关联的模型名小写(){
   return $this->belongsToMany('需要关联模型的命名空间','多对多模型的关系表名',
       '当前模型的关系键','被关联模型的关系键');
}

注意:根据案例需求,此处的关系映射依旧写在文章模型中


//3.多对多
public function moreToMore(){
   $data = \App\Admin\Article::get();          //$data  Illuminate\Database\Eloquent\Collection 对象
   //循环输出
   foreach($data as $key=>$value){             //$value App\Admin\Article模型对象
       echo '文章编号:'.$value->id.';&emsp;'.'文章名称是:'.$value->article_name.';&emsp;'.'其所用的关键词有:<br>';
       //$value->keyword 这里的keyword是模型里面的方法!!!
       //输出全部的关键词
       foreach($value->keyword as $k=>$v){     //$v  App\Admin\Keyword模型对象
           echo '&emsp;'.$v->keyword.'<br>';   //keyword是字段!!!
       }
   }
}

效果:

image.png



3.18 项目初始化

① 下载框架


② 创建数据库,修改.env文件,配置数据库连接操作


③ 设置网站本地化为中文

a、下载语言包

b、复制下载的语言包到网站resources/lang/目录下面

c、修改配置文件config/app.php 

image.png


④ 设置时区

image.png


⑤ 清理项目(删除不需要的文件)

a、删除app/Http/Controllers/Auth目录,项目中自定义登录逻辑

image.png

b、删除database/migrations/目录下面自带的数据迁移文件

image.png

c、删除database/seeds 目录下面的默认填充器文件

image.png

d、删除resources/views 目录下的welcome.blade.php文件


e、public目录下面的css、js文件也可以删除

image.png


⑥ 关闭mysql严格模式

编辑config/database.php 文件,将strict 由true修改为false

image.png

严格模式功能说明:

不支持对not null 字段插入null值

不支持对自增字段插入 '' 值

不支持text字段有默认值


⑦ 安装debugbar工具(开发的时候可选,线上别安装)

条件:php版本>=7.0,.env环境需要设置APP_DEBUG=true  !!!

a、安装

composer require barryvdh/laravel-debugbar:~v3.3.0

b、修改配置文件config/app.php


Barryvdh\Debugbar\ServiceProvider::class,
'Debugbar' => Barryvdh\Debugbar\Facades\Debugbar::class,

效果:

image.png



3.19 其他总结

① 自定义code和msg

a、在app目录下创建common\SystemCode.php  SystemMessage.php文件

interface SystemCode{
   /*
   |--------------------------------------------------------------------------
   | 网络请求类code
   |--------------------------------------------------------------------------
   |100 + 1xx 格式,如:100101
   */
   const REQ_METHOD_ERRCODE = 100101;
   const REQ_PARAM_ERRCODE = 100102;
   const NO_PRIVILEGE_CODE = 100103;
   const TOKEN_EXPIRE_CODE = 100104;
   const FORBIDDEN_CODE =  100105;

}


/**
* 接口提示信息类
*/

interface SystemMessage{

   const REQ_METHOD_ERR = '请求方式错误';
   const REQ_PARAM_ERR = '请求参数错误';
   const NO_PRIVILEGE = '没有权限';
   const TOKEN_EXPIRE = '登录已过期';
   const FORBIDDEN = '服务器拒绝请求';
}


b、在控制器中使用code和msg

public function adminList(Request $request){
   if($request->isMethod('GET')){
       return view('admin.admin.adminlist');
   }else{
       $data = [];
       $param = ['code'=>SystemCode::REQ_METHOD_ERRCODE,'msg'=>SystemMessage::REQ_METHOD_ERR,'data'=>$data];
       return response()->json($param);
   }
}


② laravel框架使用ajax  post方式删除数据

②.① meta标签方式

a、在meta标签中添加csrf_token字段和值

<meta name="csrf-token" content="{{ csrf_token() }}">

b、删除按钮

<button type="button" class="btn btn-danger btn-md"  onclick="del(this,{{$prilist->id}});">删除</button>

c、确保ajax发送之前添加X-CSRF-TOKEN

$.ajaxSetup({

    headers: {

        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')

    }

});

d、发起服务器请求

image.png


②.② ajax 的data属性值里面传递

image.png


③ laravel框架ajax提交数据,验证错误消息返回抛出提示

image.png




【原创】 酸辣鸡杂
17 05 2020

        周末又到了,迫不及待搞吃的,等星期天等了好久!

        这一次换一个高嘌呤的菜,虽然好吃,不过这玩意尽量别多吃,就是它“泡椒鸡杂”!

        作为一个美食爱好者,我不仅喜欢吃,而且还特别喜欢制作美食的过程,手把手地去弄菜,并且结果达到理想的味儿,一个满意的结果不枉费过程的辛苦,是对自己认可,是信心的提升,充满了许多体验。

        首先分享一下做“酸辣鸡杂”的材料:超市搞一斤鸡杂,包括鸡肠、鸡心、鸡血、鸡肝、鸡胗(俗称鸡郡肝也叫鸡胃),5瓣大蒜切片,小米辣泡椒、野山椒切碎,一片酸萝卜切条,芹菜或者葱黄,一坨老姜剁碎,有嫩姜也可以嫩姜切丝,15粒花椒。



鸡杂1.png


        过程:第一步、白酒加盐搓洗鸡杂十余次,特别是鸡肠鸡胗更要反复搓洗,剥去鸡胗包裹粮食的黄色黏膜,洗干净之后鸡肠切成短节,鸡胗先横切再竖切,切成像散开的花一样。

        第二步、锅里烧水,水开把鸡胗放入水中煮一下,过半分钟捞起来;洗锅放三勺油,油开下15粒花椒,下鸡杂、鸡心、鸡肠(动作要快姿势要帅,不要把花椒炸糊了,切记、切记、切记),开大火翻炒,下老姜末,下泡椒野山椒,下酸萝卜大蒜片,再来一勺子郫县豆瓣酱,撒上一盖子高度白酒,再度翻炒,翻炒过后来半碗长江水(水不能太多,刚好满过锅中食物),盖盖子煮上两三分钟,开盖下鸡血,轻轻翻炒,鸡血熟了之后开小火放盐、味精、香油、芹菜、或者葱黄(芹菜、葱黄选其一)等调料翻炒搅拌均匀,出锅关火上桌子开整!!!


鸡杂3.png


【原创】 红烧鲫鱼
12 04 2020

        又是一个周末,每周最开心的时刻,也是每周唯一 一顿荤菜。

        说到搞吃的,怎么能少得了鱼呢!

        今天要分享的菜“红烧鲫鱼”,我会记录下这次做菜的过程以及配料。首先说一下做红烧鲫鱼的配料:2条六七两的鲫鱼,半个大蒜切片,半个大蒜剁成蒜末,泡椒小米辣、泡椒野山椒各10个全部剁碎,一坨老姜剁碎,两根嫩姜切丝,酸豇豆切短节(没有酸豇豆用一片酸萝卜代替也可以),水煮鱼调料半包,香菜、小葱个一颗。

       



红烧鲫鱼.jpg



        过程:第一步、鲫鱼去鳞片(也可以不去)背面划三道小口子,面粉、鸡蛋清、烧酒涂抹鲫鱼全身腌制十分钟,锅里烧油至油开,锅中放少许盐,再开小火油炸鲫鱼炸至两面金黄捞出。第二步、洗锅烧油,放辣椒末、大蒜末、酸豇豆、水煮鱼调料包、一勺郫县豆瓣酱、剁碎的老姜末一起翻炒,炒香之后锅中加半碗水(水不多也不少),水开下炸好的鲫鱼,放嫩姜丝、大蒜片,再撒一勺子烧酒,红烧十分钟,一遍红烧一遍淋锅中的汤汁,十分钟左右放盐、味精调味,一切OK准备出锅,撒上小葱或者香菜,端到桌子上开干!!!




【原创】 麻辣水煮鱼
05 04 2020

        鱼,我的最爱!

        记得09年在深圳的时候,每个月发工资都会和卓别林去吃一顿水煮鱼,也是那个时候开始学着做鱼吃。小时候最爱田头抓鱼、扣鱼鳅儿黄鳝、逮壳蚂儿,这或许就是爱吃鱼的原因,今年回成都第一回儿弄鱼吃,没有失望,爽得很嘛!

        分享一下我煮鱼的做法及配料:2斤草鱼片、半个大蒜切片、10个干辣椒(鱼片起锅洒在鱼片表面淋热油)、泡椒小米辣剁碎、一片酸菜切丝、两片泡萝卜切片、嫩姜切丝、绿豆芽、香菜、小葱、半包水煮鱼调料、两坨老姜半个大蒜剁成渣。


 

水煮鱼.jpg

 

        做法:鱼片用烧酒、鸡蛋、豆粉搅拌腌制10分钟。准备起锅烧油,下泡椒小米辣,下老姜大蒜末,下酸菜,下煮鱼调料包,下一勺郫县豆瓣酱,搅拌翻炒,炒香以后下一碗长江水煮开,下萝卜片,下嫩姜丝,下大蒜片,水开下鱼头鱼骨头,鱼头鱼骨头煮熟捞起来,下鱼片,大火煮1~3分钟,放味精鸡精调味,餐盘底部放事先准备好的绿豆芽,捞起鱼片,鱼头鱼片覆盖在绿豆芽上,泼洒鱼汤,洗锅烧两勺油,干辣椒撒在出锅的鱼片上,油开淋上热油,撒上葱花和香菜,出锅啦,开始享受成果吧!!!


水煮鱼鱼2.jpg




【原创】 Linux系统测试网络带宽
26 03 2020

linux系统下测试带宽


第一步、安装speedtest

在linux操作系统下执行下载命令: wget https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py

第二步、授权

chmod a+rx speedtest.py

mv speedtest.py /usr/local/bin/speedtest

chown root:root /usr/local/bin/speedtest

第三步、使用speedtest命令测速

执行命令:speedtest


测速2.png


【原创】 炒酸菜
07 02 2020

        在家没事干的我又开始回忆小时候的味道。

        昨天,我炒了一个小时候最爱的素菜,“炒酸菜”,又辣又爽,越辣越想吃,越辣还越过瘾,超级下饭,又开始记录下快乐地过程。

        过程:

        第一步、酸菜坛子里面捞酸菜、酸萝卜(或者胡萝卜)、泡椒小米辣、酸姜,山坡上扯把蒜苗、盐须。酸萝卜酸菜切碎,小米辣剁碎(越细越好,辣得越巴适),泡姜切丝或者切碎都可以,盐须和蒜苗切短节。



酸菜1.jpg


酸菜2.jpg


第二步、起锅烧油,天然气开大火,油开放剁碎的酸辣椒,姜,翻炒,炒香放酸菜胡萝卜反复翻炒,再放蒜苗炒两锅铲,最后放盐须快速翻炒,开小火,放调料鸡精、味精、少许盐或者不放盐、藤椒油,出锅开干!!!


酸菜3.jpg

        

【原创】 煎鸡蛋
03 02 2020

        这个假期在家待得够久的。

        目前上班是回不去了,无聊就在山坡上走走晒晒太阳,每天三顿做饭洗碗,昨天晚上搞了一个香葱煎鸡蛋,味道恰到好处,记录下愉快地过程。

        过程:

        第一步、首先准备好10个刚从鸡窝里捡回来的鸡蛋,把鸡蛋敲出来,适当放盐,用筷儿疯狂搅拌至均匀,切记一定要把盐搅拌均匀。

        第二步、天然气开小火(一定一定一定开小火,要不然鸡蛋很快就糊了),锅中倒油,油开放入刚才搅拌均匀的鸡蛋,待背面煎至金黄,翻过来煎另一面,待两面都煎至金黄,用锅铲将鸡蛋切开为多份,这个时候不用放盐也不要放其他调料,将鸡蛋铲起来装入盘中,撒上葱花,完工,开吃!!!


鸡蛋1.jpg

第一步


鸡蛋2.jpg

第二步


鸡蛋3.jpg

开干!!!


【原创】 使用Navicat链接mysql数据库
16 09 2019

    一、使用Navicat链接mysql数据库

    ①登录云服务商,在安全组中放行3306端口,出口、入口都添加。

    

    ②按如下所示配置参数,点击确定保存。

    

    ③进行授权操作。

    GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'youpassword' WITH GRANT OPTION;
    重载授权表
    FLUSH PRIVILEGES;

    ④检查防火墙有没有屏蔽3306端口,查看开放端口,有3306则没蔽,没有则被屏蔽,屏蔽的情况下自行添加,

    操作如下:

    查看防火墙端口:firewall-cmd --zone=public --list-ports  或者   firewall-cmd --list-ports

    添加防火墙端口:firewall-cmd --zone=public --add-port=3306/tcp --permanent

    重启防火墙端口:firewall-cmd --reload

    防火墙.png

    ⑤在本机Navicat中新建链接,链接Mysql,输入远程IP、端口、登录账户、密码保存,测试链接,return 'OK';

    


    二、mysql设置环境变量

    ①找到环境变量

        windows + e,在弹出框找到此电脑,鼠标右键->属性,找到高级系统设置

        图片.png


    ②找到环境变量设置按钮

         图片.png


    ③新建环境变量,变量值为本机安装的mysql路径

        图片.png


    ④编辑系统变量Path,在其他值后面添加%MYSQL_HOME%,然后点击确定->确定

        图片.png

    

    ⑤测试成功与否,windows+r打开命令行工具输入cmd,在命令行窗口输入mysqldump,看到如下黑窗口则环境变量设置成功

        图片.png

            

        图片.png


    ⑥登录mysql并设置密码,输入mysql -u root -p,默认没有密码直接回车,登录到mysql,执行以下修改命令,Query OK说明修改成功

        图片.png

            

        图片.png


【原创】 TP5.1框架
13 04 2019

PHP框架 - ThinkPHP5.1

一、composer安装

        1.1 安装地址:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/   或者  composer config -g repo.packagist composer https://packagist.phpcomposer.com

二、ThinkPHP安装

        2.1 安装具体版本命令:composer create-project topthink/think=5.1.41 51test

        image.png

        ① 安装不成功,切换一下镜像:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer

        image.png

        image.png

        ② 如果需要更新项目版本,直接进入项目根目录,直接运行如下代码:composer update topthink/framework

三、ThinkPHP框架

        3.1 URL解析模式

        ① 普通模式:

        image.png

        ② pathinfo模式:

        image.png

        ③ rewrite模式:需要修改配置文件,打开apache的httpd.conf文件, 搜索mod_rewrite.so, 把前面的#去掉就行;然后在index.php入口文件的统计文件目录下新建.htaccess文件(此文件框架安装以后默认有)

        image.png

        ④ 兼容模式:

        image.png


        3.2 模块设计

        ① 绑定模块:修改public/index.php文件

        image.png

        3.3 控制器

        ① 修改命名空间的应用名称:在项目的根目录新建一个.env的文件,里面指定应用名

        image.png

        image.png

        image.png

        ② 渲染输出

        ②.① 直接return

        image.png

        ②. 使用json输出,return  json(), 两种形式都可以

        image.png

        ②.③ 模板输出,     return view()


        ③ 控制器前置操作

        image.png

        ④ 跳转和重定向

        ④.① 

        image.png

        ④.②  跳转页面设置,根目录/config/app.php配置文件中修改

        image.png


        ⑤ 空方法和空控制器

        ⑤.① 空方法

        image.png

        ⑤.② 空控制器    在对应模块目录下新建一个Error.php, config/app.php默认空控制器名称是Error

        image.png

        image.png

        image.png

        3.4 数据库操作

        ① 操作数据库

        image.png

        ② 模型    处理和配置数据库相关信息

        image.png

        image.png

        image.png

        ③ 基本查询操作

        ③.①  基本查询操作

        image.png

        image.png

        image.png

        ③.②  更多查询操作

        image.png

        ④  新增数据

        image.png

        image.png

        image.png

        image.png

        ⑤  修改数据

        image.png

        image.png

        image.png

        image.png

        ⑥  删除数据

        image.png

        ⑦区间查询

        image.png

        image.png

        image.png

        ⑧ 其它查询    exp表示自定义的,where第三个参数自己发挥

        image.png

        ⑨ 时间查询

        ⑨.① 传统查询方式:

        image.png

        ⑨.② 快捷查询方式:

        image.png

        ⑩ 固定查询

        image.png

        image.png

        ①① 其它查询

        image.png

        ①② 聚合、原生和子查询

        image.png

        ①②.①  子查询:

        image.png

        image.png

        ①②.②  链式操作

        image.png

        image.png

        ①②.③  field

        image.png

        image.png

        注意:第5条的 field(true) ,数据库查询的时候不用回表,效率比 * 高多了

        ①②.④  链式操作下..

        limit

        image.png

        page

        image.png

        order

        image.png

        group

        image.png

        image.png

        having

        image.png

        

        3.5 模型

        ① 模型定义

        image.png

        ② 设置模型

        image.png

        image.png

        ③ 模型操作

        image.png

        注意:第2条,数据库操作返回的数据接口是数组数组,模型操作返回的是对象数组,对象数组

        ④ 模型新增数据

        image.png

        image.png

        image.png

        image.png

        ⑤ 模型删除数据

        image.png

        image.png

        ⑥ 模型修改

        image.png

        image.png

        image.png

        image.png

        ⑦ 模型查询

        image.png

        image.png

        image.png

        image.png

        ⑧ 模型获取器

        image.png

        image.png

        ⑨ 模型修改器

        image.png

        ⑩ 模型搜索器

        image.png

        image.png

        image.png

        控制器中:

        image.png

        模型中:

        image.png

        ①① 模型数据集

        image.png

        image.png

        image.png

        ①② 模型自动时间戳和指定字段

        image.png

        image.png

        ①③ 模型类型转换和数据完成

        image.png

        ①④ 模型查询范围

        image.png

        image.png

        image.png

        ①⑤ 模型输出

        image.png

        image.png

        

        3.6 JSON字段

        image.png

        ① 在数据库创建一个json字段

        image.png

        ② 添加数据

        image.png

        image.png


        3.7 路由

        ① 路由定义

        image.png

        image.png

        image.png

        image.png

        image.png

        ② 路由的变量规则和闭包

        image.png

        image.png

        image.png

        ② 路由地址

        image.png

        image.png

        image.png

        image.png

        ③ 路由缓存

        image.png

        ④ 路由参数

        image.png

        image.png

        ⑤ 快捷路由

        image.png

        ⑥ 路由分组

        image.png

        image.png

        image.png

        image.png

        ⑦ 路由注解

        image.png

        ⑧ 路由MISS

        image.png

        image.png

        image.png

        ⑨ 跨域请求

        image.png

        image.png

        image.png

        image.png

        ⑩ 路由绑定

        image.png

        ①① 路由别名

        image.png

        ①② 资源路由

        image.png

        image.png

        image.png

        ①② 域名路由

        image.png

        image.png

        image.png

        ①③ 域名绑定

        image.png

        ①④ 路由URL地址生成

        image.png

        image.png

        image.png

        image.png

        

        3.8 请求对象

        ① 请求对象

        image.png

        image.png

        image.png

        image.png

        ② 请求信息

        image.png

        image.png

        ③ 请求变量

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        ④ HTTP头信息

        image.png

        ⑤ 伪静态

        image.png

        ⑥ 参数绑定

        image.png

        image.png

        ⑦ 请求缓存

        image.png

        ⑧ 响应操作

        image.png

        image.png

        ⑨ 文件下载

        image.png

        

        3.9 容器和依赖注入

        ① 依赖注入

        image.png

        image.png

        ② 容器

        image.png

        image.png

        image.png

        ③ facade

        image.png

        image.png

        image.png

        image.png

        image.png

        

        3.10 钩子和行为

        ① 概念

        image.png

        ② 案例演示

        image.png

        image.png

        image.png

        image.png

        image.png

        

        3.10 中间件

        ① 中间件定义

        image.png

        image.png

        image.png

        image.png

        ② 前后置中间件

        image.png

        ③ 路由中间件

        image.png

        image.png

        image.png

        image.png

        ④ 控制器中间件

        image.png

        image.png

        

        3.11 异常处理

        ① 异常处理

        image.png

        image.png

        image.png

        image.png

        

        3.12 日志处理

        ① 日志处理

        image.png

        image.png

        image.png

        image.png

        image.png

        

        3.13 验证器

        ① 验证器定义

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        ② 验证场景

        image.png

        image.png

        ③ 验证静态调用

        image.png

        ④ 表单令牌

        image.png

        image.png

        ⑤ 验证规则

        image.png

        

        3.14 session

        ① session

        image.png

        ② scookie

        image.png

        image.png

        image.png

        image.png


        3.15 多语言

        ① 多语言配置

        image.png

        image.png

        image.png

        


        3.16 文件上传

        ① 单文件上传

        image.png

        image.png

        ② 多文件上传

        image.png

        image.png


        3.17 缓存功能

        ① 缓存配置

        image.png

        image.png

        image.png

        

        3.18 验证码功能

        ① 验证码

        下载验证码命令:composer require topthink/think-captcha=2.0.*

        image.png

        image.png

        image.png

        image.png

        

        3.19 数据库事件

        ① 数据库事件

        image.png

        image.png

        ① 模型事件

        image.png

        image.png

        

        3.20 关联模型

        ① 关联模型定义

        image.png

        image.png

        主表模型

        image.png

        附表模型

        image.png

        控制器

        image.png

        image.png

        image.png

        image.png

        ② 一对一关联查询

        image.png

        image.png

        ③ 一对多关联查询

        image.png

        image.png

        image.png

        ④ 关联预载入

        image.png

        image.png

        image.png

        image.png

        ⑤ 关联统计

        image.png

        ⑥ 关联输出

        image.png

        ⑦ 多对多关联

        image.png

        image.png

        image.png


【原创】 PHP基础三
11 04 2019

PHP面向对象编程

一、面向对象基本使用

        1.1 面象对象关键字

        image.png

        1.2 实例化对象

        image.png

        image.png

        image.png

        image.png

        操作实例对象:

        image.png

        总结:

        image.png

        image.png

        1.3 访问修饰限定符

        image.png

        1.4 类的内部对象

        image.png

        image.png

        此时引出$this内置对象,在类的内部来访问成员属性和方法

        总结:在类的内部,$this代表的是对象,而$this所在的环境为类的内部的方法内部,所以能访问public、protected、private修饰符修饰的成员属性

        image.png

        image.png

        image.png

        1.5 面向对象开发规范

        image.png

        1.6 构造方法

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        构造方法的意义:构造方法是对象实例化的时候用来初始化对象资源的,通常是用来初始化对象的属性或者其他资源

        注意:之前说的new 类名和new 类名()没有区别是因为没有构造方法,或者构造方法没有参数限定,一旦构造方法有 参数限定,new 类名就不能直接用了

        1.7 析构方法

        image.png

        定义:析构方法__destruct(),是一种类结构中的特殊方法,对象在销毁的时候会自动调用

        image.png

        image.png

        image.png

        1.8 对象传值

        image.png

        定义:对象传值,其实就是将保存的对象的变量赋值给另外一个变量,在PHP中,对象的传值是“引用传递”,两个变量指向同一个对象的内存地址,即只有一个对象。

        image.png

        1.9 范围解析操作符(类常量访问)

        image.png

        定义:范围解析操作符是由两个“::”组成的,是专门用于类实现类成员操作的,可以实现类直接访问类成员。

        image.png

        image.png

        1.10 静态成员

        image.png

        定义:静态成员,使用static修饰的类成员,表示该成员属于“类访问”,PHP静态成员有两种,静态方法和静态属性 

        ① 静态属性:在类中定义属性的时候使用static关键字修饰,访问的时候只能使用  类 + 范围解析操作符 + 静态属性访问

        image.png

        ② 静态方法:在类中定义方法的时候使用static关键字修饰,访问的时候只能使用  类 + 范围解析操作符 + 静态方法名字()访问

        image.png

        注意:任何时候访问静态成员属性、方法都要用   类名 + 范围解析操作符(::) +属性/方法,不管是在类内部还是类外部

        image.png

        image.png

        image.png

        1.11 self关键字

        image.png

        定义:self关键字是一种在类的内部(方法里面)使用,代替类名的写法,能够保障用户方便修改类名字

        ① self代替类名

        image.png

        ② self也可以在类的内部方便实例化对象,比如构造方法被私有化之后,就没有办法在类的外部实例化对象,此时可以在类的内部实例化对象

        image.png

        在类的方法内部return  new self();

        image.png

        image.png

        注意:self只能在类的内部使用

        1.12 类的加载

        image.png

        定义:类的加载本质是类的访问,必须保证类在内存中已经存在,所以需要再用类之前将类所在的PHP文件加载到内存中

        ① 手动加载:即要访问某个类之前,使用文件包含,将类所在的文件加载进来

        image.png

        注意:加载类文件是一件比较消耗资源的方式,所以有些时候不确定类是否存在内存中,可以使用class_exists()函数来判断是否存在,不存在才加载

        image.png

        ② 自动加载:PHP没有那么只能的系统自动加载,所谓的自动加载只是PHP提供了一种加载机制,即实现一个__autoload()函数,当系统需要使用类,而内存中又不存在的时候,系统就会自动调用__autoload()函数来加载类文件。

        image.png

        image.png

        1.13 对象克隆

        image.png

        定义:克隆对象clone,即通过已有的对象复制一个新的同样的对象,但是两者之间并非 同一个 对象

        image.png

        image.png

        如果不允许对象被克隆,可以将__clone()方法私有化(本质是不允许对象在外部被克隆)

        image.png

        image.png

        

二、设计模式

        2.1 单例模式

        image.png

        定义:单例模式,是一种类的设计最多只会产生一个对象的设计思想

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        问题来了,如下:

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png

        image.png


        2.2 工厂模式

        image.png

        定义:工厂模式,是指像工厂流水线一样生产对象,由一个地方生产对象,其他位置就不需要额外实例化对象,从而可以方便后期代码统一的维护。而且工厂模式下,可以方便隐藏真实的类结构,因此也更加安全。

        ① 工厂模式针对的是“相同模型”的统一产出,即工厂模式产出对象对应的类都有相同的结构或者功能,所以,首先要有一批具有类似功能的类(其实本质是同样的大类下的小类)

        image.png

        ② 以前访问这些类都需要new来实现,多处使用就多次new,如果工厂模式的话,就需要增加一个工厂类

        image.png

        ③ 上述工厂类在对象生产的时候,额外产生了一个工厂类的对象,该对象无实际意义,因此可以使用更优的方式来生产对象,即静态工厂

        image.png

        ④ 以上模式虽然也是工厂生产对象,但是是建立在使用者知道类名的情况下,而且如果原类名修改,依然需要多处修改代码,所以没有达到工厂模式的真实目的

        image.png

        image.png

        

三、面向对象高级

        3.1 面向对象三大特性

        面向对象中,三大特性有封装、继承、多态

        3.1.1 封装特性

        image.png

        定义:字面意思就是将内容装到某个容器中,并进行密封保存。在面向对象思想中,封装指将数据和数据操作捆绑到一起,形成对外界的隐蔽,同时对外提供可以操作的接口。

        数据:即要操作的数据,具体就是成员属性(属性和静态属性)和类常量,这些都是在类的内部定义,用来保存数据的

        数据的操作:即数据加工过程,在面向对象的具体体现就是方法,内部定义业务逻辑对数据进行加工处理。

        捆绑到一起:即使用类结构{}将属性、类常量和方法存到一起,成为一个整体

        对外提供可操作的接口:即提供外部访问的类成员(通常是方法)

        image.png

        image.png

        总结:封装,将数据和数据操作捆绑到一起,形成一定的隐蔽性,对外提供类中公有方法的访问

        

        3.1.2 继承特性

        image.png

        定义:继承,即有些类似的对象中,下面可以细分出一些小类,然后一些公共的特性可以在一些基础类中体现,而其他相似或者较小类可以直接使用上级类中的公共代码

        ① 继承的基础:子类  父类之间本身是一种包含与被包含关系,如此才有可继承的前提

        image.png

        ② 继承关键字:extends,子类想要继承父类,则必须在子类结构申明时使用extends关键字来继承相关类

        image.png

        ③ 继承效果:子类可以不用自己去实现某些效果,可以直接访问父类中已经存在的成员

        image.png

        image.png

        3.1.3 多态特性

        image.png

        多态实现的条件:① 必须有继承,即有子类也有父类  ② 必须有父类的引用指向子类的对象  ③ 必须有方法的重写,即子类必须对父类的某些方法根据自己的需求进行重写,方法名都是相同的

        

        image.png

        image.png


        3.2 PHP继承

        image.png

        3.2.1 继承的效果

        image.png

        3.2.2 继承的目标

        继承本质是针对同类有包含关系的共性继承,即父类通常是包含子类,子类属于父类,所以在父类中通常定义的是子类共有的一些特性成员,这是开发者默认遵循的规则

        image.png

        3.3 有限继承

        image.png

        定义:有限继承,指子类在继承父类成员的时候,并非继承所有内容,而是继承并使用部分内容

        ① 继承内容:PHP中继承是子类继承父类所有的 公有成员、受保护成员和私有成员,不能继承父类的私有方法

        image.png

        ② 受保护继承,protected关键字的产生本身就是纯用于继承的,表示允许被子类在子类的内部访问,而不允许在外部被直接访问

        image.png

        ③ 访问父类私有成员,子类要想访问父类私有成员,那么是父类提供了能够访问私有成员的接口,即提供了公有或者受保护的方法给子类访问

        image.png

        ④ 静态成员(类常量)也遵循继承规则,只是访问方式是由类进行访问

        image.png

        ⑤ 构造方法和析构方法也是可以被继承,此时需要注意子类对象实例化时对应的父类构造方法的参数

        image.png

        

        3.3 重写

        image.png

        定义:重写,即子类中定义了与父类重名的成员,子类可以重写父类任意类成员,通常重写是用来重写父类的方法,用于扩展或者更改某些业务逻辑

        ① 子类继承父类,同时子类定义与父类同名的类成员

        image.png

        ② 重写父类成员之后,子类只会直接访问子类的成员(覆盖)

        image.png

        注意:不管是公有的、受保护的属性,一旦重写,父类的就会不存在(被覆盖掉),而私有属性是不会被覆盖而丢失的

        image.png

        ③ 重写的要求1:子类重写父类的方法,控制权不能高于父类,即子类可以比父类更开放

        image.png

        ④ 重写的要求2:PHP中重写要求子类重写父类方法的时候,必须保证与父类同名方法参数一致;方法参数不单单要求数量一致,数据类型也要一致,PHP7以前对重写没有要求

        image.png

        ⑤ 重写的要求3:重写针对的是被继承的成员,父类私有方法不会被继承,因此不受要求2规定

        image.png

        ⑥ 重写是指子类拥有特殊的情况,一般是需要再父类的基础上进行扩展,此时如果想要保证父类被重写的方法继续执行(默认只访问子类重写的新方法),需要在子类重写方法的时候使用  parent 关键字

        image.png

        注意:“parent”不能访问父类的属性,可以访问静态属性、静态方法、类常量和普通方法

        image.png

        

        3.4 PHP继承的特点

        ① PHP中的继承只能是单继承,即子类只有一个父类

        ② PHP如果想继承多个类,可以使用链式继承

        image.png

        ③ PHP中继承只有私有方法不能被继承

        ④ PHP允许子类继承父类中的构造函数和析构函数

        

        3.5 静态延迟绑定

        image.png

        image.png

        image.png

        image.png


        3.6 最终类final

        image.png

        定义:最终类,使用final关键字修饰类名,表示此类不可以再被继承

        ① 基本使用

        image.png

        ② final关键字不止修饰类表示类不可以被继承,还能修饰方法,表示方法不能被重写

        image.png

        image.png

        3.7 abstract抽象类

        定义:抽象类,使用abstract关键字修饰的类,“表示该类只能被继承,不能被实例化”!!

        ①  abstract修饰类

        image.png

        ②  abstract修饰方法,abstrac修饰的方法不能有方法体,而且又抽象方法的类必须声明为抽象类

        image.png

        image.png

        ③  抽象方法因为要被子类继承实现,所以不能使用private修饰(私有的方法不会被继承)

        image.png

        image.png

        3.8 接口interface

        image.png

        定义:接口,使用interface关键字定义,与类类似,专门用来规范一些共性类必须实现的方法

        ① 接口不是类,不能实例化

        image.png

        ② 接口实现,接口是用来规范类必须完成的事情,所以“接口只能被类实现”,使用implements实现

        image.png

        ③ 接口成员,接口中只能定义公有抽象方法和接口常量

        image.png

        image.png

        image.png

        image.png

        image.png


        3.9 trait代码复用

        image.png

        定义:Trait是为类似PHP的单继承语言准备的一种代码复用机制,trait使得单继承语言摆脱为了复用而不得不继承的尴尬,让面向对象更加纯粹

        ① trait是一种类似class的关键字

        image.png

        ② trait内部可以拥有一个能拥有成员属性(包含静态),成员方法(包含静态),但不能有类常量

        image.png

        ③ trait是用来实现代码复用的,不能被实例化,也不可以被继承

        image.png

        ④ trait是用来将公共代码提供给其他类使用的,而类要使用trait的前提是加载对应的trait

        image.png

        ⑤ 一个类可以使用多个trait 

        image.png

        ⑥ 如果同时引入多个trait中有重名的方法,那么会产生冲突,解决冲突的方式是使用insteadof代替处理,以及对被替代方法使用别名

        image.png

        image.png

        


        3.10 PHP重载

        image.png

        image.png

        

        image.png

        image.png

        image.png

        image.png

        image.png

        

        image.png

        image.png

        image.png

        image.png


        3.11 foreach遍历对象

        image.png

        ① 类的外部遍历实例化对象,只能遍历共有的

        image.png

        ② 在类的内部遍历,公有的、私有的、受保护的,都可以遍历出来

        image.png



【原创】 PHP基础二
28 03 2019

PHP基础 - 面向过程编程

一、PHP基础

        1.1 php语法

        1.1.1 PHP代码标记

        asp标记:<%  php代码  %>

        短标记:<?  php代码  ?>    

        短标记方式需要修改:short_open_tag = Off   改为  short_open_tag = On

        脚本标记:<script language="php"> php代码 </script>

        标准标记:<?php  php代码  ?>,标准标记可以省略结尾?>,以<?php   开始

        短标记需要开启php.ini配置文件,asp标记和script标记在php7中已经被移除,并且短标记在php7.3版本也已经移除!!!

        1.1.2 PHP语句分隔符

        在php代码中使用“;”英文太的分号作为语句分割符号


        1.2  php变量

        1.2.1 php变量基本概念

        image.png

        1.2.2 php变量使用

        image.png

        image.png

        1.2.3 php变量命名规则

        image.png

        1.2.4 预定义变量(又叫超全局变量)

        预定义变量:提前定义的变量、系统定义的变量!!!

        image.png

        1.2.5 可变变量

        含义:如果一个变量保存的值刚好是另一个变量的名字,那么可以直接通过访问一个变量得到另一个变量的值,在变量前面再多加一个$符号

        image.png

        1.2.6 变量传值

        image.png

        image.png

        值传递:

        image.png

        引用传递(址传递): $a = &$b

        image.png

        image.png

        1.3 常量

        image.png

        1.3.1 常量定义:

        1. 使用函数方式: define('常量名',‘常量值’);

        2. 使用const关键字方式: const 常量名 = 值;

        1.3.2 常量名定义规则:

        image.png

        注意:define和const定义常量的区别

        1. const是一个语言结构,define是一个函数

        2. const不能在条件语句中定义,而define可以

        3. const可在类中使用,而define不能

        4. const用于类成员变量的定义,而define不能用于类成员变量的定义

        5. const定义时大小写敏感,define可以通过第三个参(为true表示大小写不敏感)数指定是否大小写敏感

        1.3.3  系统常量

        image.png

        特殊系统常量(魔术常量):

        image.png


二、PHP数据类型

        2.1 数据类型说明

        在php中,指的是存储的数据本身的数据类型,而不是变量的类型

        2.1.1 PHP八种数据类型

        php中数据类型分为三大类八小类

        image.png


        2.2 类型转换

        在很多条件下,需要指定的数据类型,需要外部数据(当前PHP取得的数据),转换成目标数据类型

        2.2.1 转换类型的2种方式

        a、系统根据自己的判断转换(用得比较多,效率偏低)

        b、强制转换,人为根据需要的目标类型转换

        2.2.2 其他类型转布尔类型为空的情况:

        ① int 的0

        ② float 的0.0 

        ③ 空字符串

        ④ 字符串的 0

        ⑤ 空数组

        ⑥ null

        2.2.3 PHP类型比较

        image.png

        2.2.4 其它类型转数值的说明:

        image.png

        image.png

        2.2.5 整数类型

        image.png

        image.png

        2.2.6 浮点类型

        image.png

        2.2.7 布尔类型

        image.png

        强制类型转换

        image.png

        2.2.8 字符串类型

        字符串定义方式:

        ① 单引号方式   

        image.png

        ② 双引号方式

        image.png

        ③ 定界符声明

        image.png

        image.png

        单引号与双引号的区别:

        ① 单引号不能解析转义字符,只能解析转义斜线“\”和自己本身

        ② 单引号不能解析变量

        ③ 单引号可以嵌套双引号,单引号嵌套双引号需要加转义斜线"\"


        ④ 双引号可以解析转义字符

        ⑤ 双引号能解析变量,双引号中的变量使用  {}括起来

        ⑥ 双引号可以嵌套单引号,双引号嵌套双引号需要加转义斜线

        2.2.9 数组类型

        什么是数组:array,数据的组合,指将一组数据(多个)存储到一个指定的容器中,用变量指向该容器,然后可以通过变量一次性得到该容器中的所有数据

        数组定义方式:

        ① 使用array()关键字

        image.png

        image.png

        ② 使用中括号来包括数据

        image.png

        image.png

        ③ 隐形定义数组,给变量增加一个中括号,系统自动变成数组

        image.png

        image.png

        PHP数组的特点:

        ① 下标可以试数字,也可以是字符串;如果是数字下标,则为索引数组,如果是字符串下标,则为关联数组,如果在下标既有数字也有字母则为混合数组

        ② 数组下标的自增长,默认是从0开始的,如果中间有手动指定下标,下一次自增长则从最大的下标开始增长

        ③ 特殊下标

        image.png

        image.png

        说明:PHP下标不要使用特殊值,PHP元素没有类型限制,PHP中数组是很大的数据,所以存储位置是在堆区,系统为数组分配一块连续的内存地址!!!

        

        PHP数组遍历的原理:

        image.png

        特殊遍历:while()  +  list()  + each()

        image.png

        image.png

        

三、PHP运算符

        3.1 普通运算符,省略...

        3.2 连接运算符

            a. 使用“.”将多个字符拼接在一起

            b. 特殊的一个,使用“.=” 将字符连接起来(复合运算,将左边的内容与右边的内容连接起来,然后重新赋值给左边的变量)

            $a .= $b     等价于  $a = $a.$b;   

        3.3 错误抑制符

        PHP中有一些错误可能提前预知,但是又不希望用户看到,可以使用错误抑制符处理,在可能出错的表达式前面使用   "@",  @($a / $b)

        3.4 三目运算符

        有三个表达式参与的运算

        表达式1 ? 表达式2 : 表达式3    ;如果表达式1成立,则运行表达式2,否则运行表达式3

        三目运算符的复合使用:

        表达式1 ? (表达式2 ?表达式3 :表达式4) : (表达式5 ? 表达式6 : 表达式7)

        3.4 自操作运算符

        自己操作自己的运算符

        ++:在原来的值上+1

        --  :在原来的值上 -1

        PHP中自操作符“++” “--”分前置操作和后置操作,前置和后置如果只有自身操作,不参与其他运算,那么效果是一样的;但是自操作的同时还参与别的运算,那么效果就不一样了

        image.png

        3.5 计算机码

        image.png

        image.png

        注意:正数的原码、反码、补码都相同,是它本身

        3.6 位运算符

        image.png

        3.7 运算符优先级

        从上往下优先级在降低

        image.png

        

四、PHP流程控制语句

        4.1 流程控制

        流程控制就是代码的执行方向

        4.2 控制分类

        image.png

        4.3 省略...

        

五、PHP文件操作

        5.1 require和include的区别

        ① require是php文件在加载的时候就加载,include是php代码执行到include的时候才加载

        ② require加载的资源不存在报致命错误,include加载的资源不存在报警告错误,include报错不影响脚本继续执行,require报错则程序终止不再往下执行

        5.2 文件加载路径

        image.png

        绝对路径和相对路径的区别:

        ① 绝对路径相对效率偏低,但是相对安全

        ② 相对路径相对效率高一些,但是容易出错(相对路径发生改变)

        

六、PHP函数

        6.1 函数参数

        形参:形式参数,不具有实际意义的参数,是在函数定义的时候用的参数

        实参:实际参数,具有实际意义的参数,是在函数调佣时使用的参数,形参是实参的载体,实参在调用时通常需要传入到函数内部参与数据计算,那么需要在函数内部去找到实际数据所在的位置才能找到数据本身:需要实际调用的时候,将数据以实参的形式传递给形参:给形参赋值,从而使函数内部可以用到函数外部的数据

        image.png

        注意:

        ① 在php中允许实参多于形参,函数内部不使用而已

        ② 实参不能少于形参个数


        6.2 引用传递

        image.png

        image.png

        image.png

        image.png

        6.3 函数返回值

        image.png

        image.png

        image.png

        注意:

        ① 函数没有return返回值,打印结果时为null

        ② 函数return以后, return后面的代码不再执行

        6.4 函数作用域

        作用域:变量能够被访问的区域

        image.png

        image.png

        函数内部修改函数外部的值:

        image.png

        image.png

        image.png

        image.png

        image.png

        6.5 静态变量

        静态变量使用static修饰,是在函数内部定义的变量,用来实现跨函数共享数据的变量

        image.png

        image.png

        静态变量的原理:系统在进行编译的时候就会对static这一行进行初始化,为静态变量赋值;函数在再次调用的时候会跳过static 定义变量这一行

        6.6 可变函数

        当前有一个变量的值,刚好是一个函数的名字,那么就可以使用变量+()的方式来充当函数名使用

        image.png

        image.png

        6.7 匿名函数

        匿名函数:没有函数名的函数

        变量名 = function(){

            函数体

        };

        image.png

        image.png

        6.8 闭包函数

        image.png

        错误使用:!!!

        image.png

        image.png

        正确使用:!!!

        image.png

        image.png

        image.png

        

七、其它

        7.1 伪类型

        image.png

        image.png

        image.png

        7.2 部分常用函数

        image.png

        image.png

        7.3 错误处理

        错误处理:指的是系统(或者用户)在对某些代码进行执行的时候,发现有错误,就会通过处理错误的形式告知程序员

        错误分类:

        image.png

        错误代码:

        image.png

        错误触发:

        ① 程序运行时触发

        ② 人为触发

        image.png

        错误显示设置:

        哪些错误该显示,以及该如何显示,在PHP中有两种方式来设置当前脚本的错误处理

        ① php.ini配置文件:全局配置

        display_errors   是否显示错误

        error_reporting  显示什么级别的错误

        系统默认的error_reporting = E_ALL     display_errors = On

        ② 在php的脚本中去设置

        

        error_log配置项:

        ① 开启配置    log_errors = On           

        ② 错误日志保存路径   error_log = '/www/err/error.log'        

        

        7.4 会话技术

        7.4.1 COOKIE的基本使用

        cookie原理:

        服务器将数据通过HTTP响应存储到浏览器上,浏览器可以在以后携带对应的cookie数据访问服务器

        image.png

        image.png

        cookie使用:

        image.png

        image.png

        注意:cookie能够实现跨脚本共享数据,cookie是存在客户端电脑,没有提供删除的功能,只有设置一个过期时间让它过期清除或者设置变量值为''空字符串

        cookie高级使用 - 数组数据:

        image.png

        7.4.2 SESSION的基本使用

        session原理:

        session与浏览器无关,但是与cookie有关

        image.png

        image.png

        session基本使用:

        使用session的时候,任何时候都要开启session,$_SESSION是通过session_start()函数定义的没有直接定义

        image.png

        ① 设置session:

        如果想要存储数据到session中,只要不断给$_SESSION数组添加元素即可

        image.png

        image.png

        ② 获取session数据:

        image.png

        image.png

        会话技术的本质是为了实现跨脚本共享数据,在一个脚本中定义数据,在另一个脚本中保存数据

        ③ 删除session数据:

        image.png

        image.png

        清除session中全部数据:

        $_SESSION = array();


        session有关配置:

        image.png

        在服务器部署的时候改一下session.save_path路径就可以了,其他基本不用改

        session常用配置:

        image.png

        session配置的形式:

        ① php.ini配置:全局配置,修改php.ini中配置项

        ② 脚本配置:使用ini_set()函数来配置,只会对当前运行的脚本有效 

        session的销毁:

        session删除指的是删除session中的数据,session销毁指的是销毁session对应的文件,系统提供一个session_destroy()函数,会自动根据session_start()得到的SESSION_ID去找到指定的session文件,并把其删除。

        image.png


        垃圾回收机制:

        image.png


        垃圾回收参数配置:

        image.png


        session禁用:

        ① 禁用cookie后如何使用session

        原理:session技术需要用到cookie技术来保存sessionID,从而使PHP在跨脚本的时候得到相同的sessionID,从而访问同一个session文件

        解决思路:最终让session_start()在开启之前拿到原来的sessionID(另外一个脚本的)

        ② 实现无cookie使用session

        在PHP中要想解决没有cookie也能实现session的方式有两种:

        方案一:可以利用PHP提供的session_id()函数和session_name()函数来获得和设置sessionID或者name从而解决session_start()产生信的sessionID的情况

        1. 在session保存数据的脚本中获取sessionID和名字,一定要在session_start()后面获取id和name

        image.png

        image.png

        2. 相伴大将数据传递给另外一个脚本(使用url或者表单传值)

        image.png

        image.png

        3. 在需要的脚本中获取数据

        image.png

        4. 阻止session_start()产生新的ID,告诉它已经存在了,使用session_id($id);

        image.png

        image.png

        方案二:可以利用session机制中已经提供的解决方案自动操作(配置)

        原因1:默认session配置只允许cookie保存sessionID

        原因2:默认关闭了其他能够传送数据的方式只保留了cookie

        

        ① 修改PHP配置文件,开启其他方式传输sessionID,关闭只允许使用cookie传输功能

        image.png

        image.png

        ② 一旦开启,PHP会自动将sessionID和session名字在其他位置绑定数据,同时还会在session_start()的时候,考虑其他方式(表单)传输数据,而不是只有cookie

        注意:使用中几乎不用方式二,就用PHP默认的方式

        



【原创】 PHP基础一
23 03 2019

PHP基础 - 软件安装

一、基本概念

        1.1 DNS

        DNS(Domain Name System,域名系统),因特网上作为域名和IP地址互相映射的分布式数据库,方便用户访问互联网。通过主机名,最终得到与该主机对应的IP地址的过程叫做域名解析(或主机名解析)。

        用户输入域名www.baidu.com -> DNS -> (www.baidu.com  110.242.68.66 )  -> 服务器主机电脑


        1.2 端口

        image.png

        同一台服务器上的服务,通过端口区分,比如web网页访问apache80端口 ,mysql服务访问3306端口等等.

        用户输入域名www.baidu.com:端口 -> DNS -> (www.baidu.com  110.242.68.66 )  -> 服务器主机电脑  -> 服务软件


        1.3 web程序访问流程

        浏览器发起访问  ->  DNS域名解析系统解析域名  -> 服务器电脑  -> 服务软件

        静态网页访问过程:

        image.png

        动态网页访问过程:

        image.png

二、apache软件

        2.1 apache软件目录结构

        image.png 

        2.2 查看apache使用模块  httpd -M

        image.png

        2.3 验证配置文件是否有效 httpd -t

        image.png

        2.4 配置默认站点

        1. 让apache确认服务器上访问的位置:网站文件缩在位置

        httpd.conf文件:DocumentRoot

        image.png

        2. 为方便用户使用文字访问对应的网站:给文件夹对应去一个别名

        httpd.conf文件: ServerName

        image.png

        默认80端口,可以修改监听端口

        image.png

        修改以后验证是否正确,可以使用httpd -t 验证,凡是修改了httpd.conf配置文件,都要重启httpd服务

        3. 实现DNS域名解析:通常默认站点都是本地DNS,hosts文件

        image.png

        

三、PHP软件安装

        3.1 php目录结构

        image.png

        3.2 php.exe的应用

        php.exe就是可以解析php代码转变成html代码,从而让浏览器可以理解

        1. 通过cmd命令行进入到php的安装位置

        image.png

        2. 通过php.exe 命令来解析要执行的php脚本   php.exe  -f    PHP文件所在的路径

        image.png

        3. 配置apache加载PHP模块

        3.1、apache加载php模块:在apache主配置文件中加载对应的php提供的模块

        LoadModule  php5_module     php所提供的模块连接所在路径

        image.png

        3.2、apache分配工作给php模块:如果是php代码就交给php处理,文件后缀判断.php结尾肯定是php代码

        AddType application/x-httpd-php  .php

        image.png

        3.3、将PHP配置文件加载到apache配置文件中:共同生效

        a、在apache中指定php配置文件所在路径  PHPIniDir   php.ini所在路径

        image.png

        b、php.ini文件默认是不存在的,是以development  和 production形式存在,需要格式化,复制一份,不要去修改原始文件

        image.png

        说明:PHP的配置文件已经加载到了apache的配置项中,意味着php.ini的修改需要apache重启才会生效

        

四、mysql软件安装

        4.1 安装选择

        image.png

        4.2 mysql目录结构说明

        image.png

        4.3 bin目录下常用命令

        image.png

        4.4 php连接mysql

        1. php加载mysql扩展:php.ini文件中取代php_mysql.dll的注释

        mysql

        image.png

        mysqli

        image.png

        2. php中所有的扩展都在php/ext文件夹中,需要指定扩展所在路径:extension_dir

        image.png

        3.php.ini是被apache加载的,所以要重启apache

        image.png

        4.5 设定php系统时区

        通过php.ini中的timezone配置项来实现