• <tbody id="baor6"></tbody>

  • <em id="baor6"><acronym id="baor6"><input id="baor6"></input></acronym></em>
    <strike id="baor6"></strike><li id="baor6"></li>
    <rp id="baor6"></rp>
    1. <em id="baor6"></em>
      <form id="baor6"></form>
      <nobr id="baor6"></nobr>

      <em id="baor6"><acronym id="baor6"><u id="baor6"></u></acronym></em>

          葵花寶典教程,一個自學編程平臺

          葵花寶典教程,一個自學編程平臺

          Golang語言小技巧1

          技巧

          •  golang可以在函數定義的時候確定其返回值具體為 func foo(arg int)(res int){}

          • go env GOPATH 可以用來去查看當前的GOPATH

          • golang 查找問題, 可以根據Goglandack工具一起結合查找

          • golang中的init函數用來初始化一些變量, 它總是會被運行, 只要導入了這個包, 初始化就會在run main之前被運行

          • golang中的接口類型, 以接口類型傳入參數, 如果該接口類型, 實現了方法則ok

          • proto.String() 是一個helper方法, 分配一個新的空間, 并返回一個指向它的指針

          • golang中首字母大寫表示public, 首字母小寫則表示protect 或者 private

          • golangdefer語句的執行順序為逆序

          • golang中有時候為了診斷方便, 可以使用printStackruntime.Stack(buf[:], false)

          • io.Writer是golang中接口類型的一種典型的運用, Fprintf=>(Printf, SPrintf)

          • Stringer接口通常用于對于printf或者println等一些列的函數數輸出

          • golang中的數組array為定長數組, 如兩個數組相比較必須是comparable即長度和類型必須一致

          • golang語言定義變量或者結構體在編譯期就已經復制, 在運行期賦值, 需要重新定義一個函數

          • golangflag庫需要使用flag.parse()來傳遞參數

          • buffer channelchannel中的元素個數小于channel size時為非阻塞的, 達到channel size之后則阻塞當前線程直到元素被取出.

          • 0 buff channel即為sync channel. 生產者和消費者都會被阻塞.

          • golang中對比并行程序設計有: 設置返回channel, 以經典的生產者消費者模式進行處理.

          • timer主要是用來設置定時任務, tickers主要是用來設置周期任務.

          • 使用sync.Mutex通過對全局變量的LockUnLock實現atomic加鎖和解鎖

          • 對于Atomic inc也可以使用sync/atomic庫實現.

          • CASCompare And Swap比較并交換, 在golang中是以共享內存方式實現的一種同步機制.

          • Share memory by communicating; don't communicate by sharing memory.

          • golang中更好的一種方式是通過sync包以及channel來實現同步機制.

          • time.Sleep vs time.After

            • time.After通常于select搭配使用, 可以設置超時機制

            • time.Sleep可讀性更強, 暫停當前Goroutine, 直到達到時間.

          • timer 通過AfterFuncNewTimer來創建, 使用Reset來重置, timer. 使用Stop來停止timer, 停止timer之后, 相應的goroutine會被阻塞.

          • timer 使用時, 如果使用了timer.Stop(), 則timer, 會被GC所回收, 但是timer對應的channel不會關閉, 則channel將會被永遠的阻塞.

          • timer.Stop對應的timer被GC所回收, timer.C被阻塞, 如果再使用timer.Reset,則重新給timer對應的時間賦值并放入timer.C

          • timer 使用的正確姿勢是, 使用timer.Reset, 而不是使用timer.Stop. 如果使用指針并且使用對應的timer.Channel. 重置timer時, 應當使用Reset而不是重新Stop+NewTimer來重置, 這樣會導致內存泄漏, 阻塞goroutine

          • deadlock死鎖: 多個線程占有一部分資源, 去請求另一部分資源時阻塞. 這些線程等等其他的線程釋放資源. (已請求到鎖)

          • livelock:活鎖, 不斷請求鎖, 但是無法請求到資源. (未加鎖)

          • selectchannel搭配使用, 如果要實現類似listener的模式, 則需要在外層加for {select ...}.

          • 通常使用select實現函數超時機制.

          • HTTP keep-alive是保持TCP連接open, 即復用TCP連接的一種手段. 例如: 通過HTTP keep-alive就可以實現不用每次都去重新建立HTTP連接, 這樣就不會重新去請求靜態資源css,html等.

          • TCP keep-alive是TCP協議定時地發送空的ack包來確認彼此的狀態.

          • TCP keep-aliveHTTP keep-alive是兩個不同的技術, 不存在誰依賴誰的關系. TCP keep-alive用來檢測對端是否存在, 而HTTP keep-alive用來協商以復用連接.

          • context上下文類型,帶有deadline,取消信號,還有其他與請求相關的request-scoped的值

          • context遵循的幾個原則:

            • 不要將Context放入結構體,使用Context應該作為第一個參數傳入,并命名為ctx,func DoSomething(ctx context.Context, arg Arg) error {//use ctx}

            • 即使函數允許,不要傳入nil的Context.如果不知道用哪種Context,使用context.TODO()

            • 使用context的Value相關的方法只應該用于在程序和接口中傳遞和請求相關元數據,不要用它傳遞可選參數

            • 相同的Context可以傳遞給不同的goroutine, Context并發安全

          • sync.Map go1.9支持的線程安全的map,通過cas實現

          • reflect: go語言反射機制。reflact反射是一種機制,這種機制可以實現自我類型的檢查和描述

          • init函數在main函數之前執行,通常用作初始化

          • sync.Once保證程序僅僅執行一次action

          • panic類似于拋出異常,即停止當前正確的程序流程, panic之后會執行defer函數

          • recover類似于恢復異常,即panic會一直向上拋出阻礙正常流程,直到recover則恢復

          • 具體的某個golang對象初始化時候,通常的一種寫法是通過OptionFunc來初始化一些可選參數

          • // +build:是golang的build tag 例如// +build linux,386 darwin,!cgo 等價于(linux AND 386) OR (darwin AND (NOT cgo))

          • go build -tags="linux 386"進行編譯, 并根據Build Constraints的條件進行編譯

          • golang make初始化并分配內存

          • golang %#v%+v 為打印變量并打印其變量名

          • value receiver 和 pointer receiver

            • value receiver是并發安全的, 且不改變value本身的值, copy by value

            • pointer receiver 不是并發安全的,且可以改變pointer本身的值

          • golang elastic 使用Scorll可以滾動的獲取所有請求的結果

          • dep 為官網golang包管理工具

          • dep init : 效率較低,初始化golang項目的獨立環境,利用gps分析出當前代碼包中的依賴關系,并將其約束寫入項目中的,Gopkg.toml文件中。將所有依賴的包最新的version/branch/revision信息寫入Gopkg.lock,創建vendor目錄,并以Gopkg.lock為輸入,將其中包下載到vendor目錄下面。

          • dep status: 查看當前項目下的status的狀態

          • dep ensure : 確保當前項目的vendor處于一個正確的狀態

          • gorilla/mux : golang 非常受歡迎的URL router dispatcher
            goconvey : golang 帶UI的單元測試框架,可以很好的顯示單元覆蓋度

          • ACL: access control list 訪問控制列表,是路由器和交換機接口的指令,用于控制端口進出的數據包,ACL提供了網絡安全訪問的基本手段。

          • map[string]*person{} 與 map[string]person{}的區別在于指針和實例,實例為重新copy構造,改變內容之后,不改變map本身的內容, 末尾的{}為初始化map

          • OLAPOnline Analytical Processing: 在線數據處理關注于數據分析,OLTP: Online Transaction Processing 在線事務處理,類似于增刪查改,專注于查詢的速度

          • 一致性hash,為了解決彈性集群動態擴容的問題,通常的做法是構造0~2^32-1個hash環狀空間,對于具體的某個key找到對應服務器上節點時,只需要順序在環上轉動找到第一個命中的節點即可。當出現負載不均的情況時,可以考慮使用引入虛擬節點達到負載均衡的效果。

          • GC: Garbage collection 垃圾回收機制,常見的垃圾回收算法有: 引用計數,標記清除Mark-Sweep法,三色標記法,分代收集法。

          • 引用計數:最基礎的垃圾回收算法,例如C++中的std:shared_ptr

          • 標記清除:分為兩個步驟:1. Mark: 從程序的根節點開始,遍歷所有的對象,對可達的節點進行標記。2. Sweep: 將所有未標記的節點對象作為垃圾進行回收清除操作。有一個問題是會有STW(Stop The World)的問題,算法進行標記時會暫停整個應用程序。當程序中的對象特別多時,遍歷整個對象樹會消耗很多的時間。go1.3

          • 三色標記:是Mark-Sweep的一個改進,支持并發,即可以實現on-the-fly即在程序執行的同時進行垃圾回收 go1.6. 步驟如下:

          1. 首先創建三個集合:白、灰、黑。
          2. 將所有對象放入白色集合中。
          3. 然后從根節點開始遍歷所有對象(注意這里**并不遞歸遍歷**),把遍歷到的對象從白色集合放入灰色集合。
          4. 之后遍歷灰色集合,將灰色對象引用的對象從白色集合放入灰色集合,之后將此灰色對象放入黑色集合
          5. 重復 4 直到灰色中無任何對象
          6. 通過write-barrier檢測對象有變化,重復以上操作
          7. 集所有白色對象(垃圾)


          • 分代收集:也是Mark-Sweep的一個改進。該算法基于一個經驗:絕大多數的對象生命周期都很短,按照對象生命周期的長短來分代。

          一般分代GC,分為3代,新生代(Young Generation),年老代(Tenured Generation),永久代(Permanent Generation)
          原理如下:
          
          1. 新對象放入第 0 代
          2. 當內存用量超過一個較小的閾值時,觸發 0 代收集
          3. 第 0 代幸存的對象(未被收集)放入第 1 代
          4. 只有當內存用量超過一個較高的閾值時,才會觸發 1 代收集,2 代同理
          因為 0 代中的對象十分少,所以每次收集時遍歷都會非??欤ū?nbsp;1 代收集快幾個數量級)。只有內存消耗過于



          git解決沖突的四種方式是什么

          四種方式:

          1. 執行命令將改動提交到遠程分支。

          2. 使用“git add xxx”和“git commit -m..”將改動提交;

          3. 執行命令來手動合并沖突的內容;

          4. 使用“git fetch origin master”將遠程分支拉下來;

          60d57c9306e48490[3].jpg

          1. git沖突的產生原因

            多個開發者同時使用或者操作git中的同一個文件,最后在依次提交commit和推送push的時候,第一個操作的是可以正常提交的,而之后的開發者想要執行pull(拉)和pull(推)操作的時候,就會報沖突異常conflict。

            Git解決沖突的方法

            使用git fetch origin master將遠程分支拉下來
            使用git merge origin master手動合并沖突的內容,首先合并代碼并輸入備注信息,然后按esc,再按shit+;,輸入wq保存并退出
            使用git add xxx和git commit -m "xxx" 將改動提交
            使用git push origin master將改動提交到遠程分支

          PHP composer

          composer是php包管理工具,使用它可以很方便進行構建項目,載入三方包,以及各種復雜依賴,自動加載等需要。


          安裝composer


          curl -sS https://getcomposer.org/installer | php -- \


          --install-dir=/usr/bin \


          --filename=composer


          安裝后,使用composer -v來查看版本號等信息。


          修改代碼倉庫源


          由于composer默認的源服務器在國外,因為眾所周知的原因,下載龜速,我們需要將其替換為國內的全量源,目前可用的有這兩個:


          來自 Laravel China


          composer config -g repo.packagist composer https://packagist.laravel-china.org


          來自 https://php.cnpkg.org/


          composer config -g repos.packagist composer https://php.cnpkg.org


          查看全部全局配置


          composer config -g --list


          查看單個項目全部配置


          composer config --list


          查看某個配置


          composer config -g repositories.packagist.org


          取消某一項配置


          composer config -g --unset repos.packagist


          創建新項目


          創建一個Yii項目


          composer create-project --prefer-dist yiisoft/yii2-app-basic basic.com


          其中create-project命令后面的--prefer-dist還可以使用--prefer-source,它們的區別:


          --prefer-dist會從github上下載.zip壓縮包,并緩存到本地。下次再安裝就會從本地加載,大大加速安裝速度。但她沒有保留 .git文件夾,沒有版本信息。適合基于這個package進行開發。


          --prefer-source 會從github上clone源代碼,不會在本地緩存(最新的版本也可以使用緩存了)。保留了.git文件夾,從而可以實現版本控制。適合用于修改源代碼。


          推薦使用--prefer-dist可以加快速度,在使用的時候有可能會有下面類似的警告:


          Failed to download yiisoft/yii2-gii from dist: The zip extension and unzip command are both missing, skipping.


          Your command-line PHP is using multiple ini files. Run `php --ini` to show them.


          環境中缺少zip,unzip工具包,安裝一下:


          apt-get install zip unzip


          之后跟的yiisoft/yii2-app-basic就是項目包名,最后面的basic.com指定新建項目文件夾。


          檢索倉庫里的包


          composer search monolog/monolog


          安裝新依賴包


          composer require monolog/monolog


          控制版本號


          # 指定版本


          composer require monolog/monolog 1.24.0


          # 版本范圍


          # 有效的運算符有 >、>=、


          # 支持通配符 *


          # 支付波浪號運算符 ~ 限定在最低版本和下一個重要版本更新之前


          # 以下都是有效的版本號


          # 版本大于等于1.0


          >=1.0


          # 版本大于等于1.0并且小于2.0


          >=1.0,<2.0


          # 版本大于等于1.0并且小于1.1,或者版本大于等于1.2


          >=1.0,<1.1|>=1.2


          # 相當于>=1.0,<1.1


          1.0.*


          # 相當于>=1.2,<2.0


          ~1.2


          # 相當于>=1.2.3,<1.3


          ~1.2.3


          # 相當于>=1.2.3,<2.0.0 在多于2位的版本號的時候跟 ~ 有區別


          ^1.2.3


          移除依賴包


          composer remove monolog/monolog


          初始化一個composer.json


          composer init


          查看已存在的包


          composer info


          根據composer.lock安裝依賴包(如果存在),否則根據composer.json


          composer install


          根據composer.json更新依賴到指定范圍內最新版,并更新composer.lock文件


          composer update


          清理緩存


          composer clearcache


          更新composer.phar


          composer self-update


          Composer常用的命令整理


          golang go-swagger為Go工程生成自動化接口文檔

          來自動生成接口文檔。文檔的格式支持兩種:一種是json,另外一種是yaml。要想通過代碼注釋生成接口文檔,那么你的Go工程必須放在$GOPATH/src目錄下。

          使用swagger:meta定義接口的全局信息

          屬性

          標記含義

          Terms Of Service描述使用接口服務的一些協議,比如免責等

          Consumes描述接口默認請求的mime類型值,如果有多個,每個類型占據一行。支持的MIME類型有json,yaml,xml,txt,bin,urlform,multipartform

          Produces描述接口默認響應的mime類型值,如果有多個,每個類型占據一行

          Schemes描述接口默認支持的協議類型,可能的值有http,https,ws,wss

          Version當前接口的版本

          Host接口服務所在的域名

          Base path接口默認的根路徑

          Contact通常來說是接口文檔編寫者的聯系方式,格式:John Danjohn.dan@example.com

          License接口文檔遵循的許可證名稱

          示例

          // Package classification testProject API.

          //

          // the purpose of this application is to provide an application

          // that is using plain go code to define an API

          //

          // This should demonstrate all the possible comment annotations

          // that are available to turn go code into a fully compliant swagger 2.0 spec

          //

          // Terms Of Service:

          //

          // there are no TOS at this moment, use at your own risk we take no responsibility

          //

          //     Schemes: http, https

          //     Host: localhost

          //     BasePath: /v1

          //     Version: 0.0.1

          //     Contact: Haojie.zhao<haojie.zhao@changhong.com>

          //

          //     Consumes:

          //     - application/json

          //     - application/xml

          //

          //     Produces:

          //     - application/json

          //     - application/xml

          //

          // swagger:meta

          package routers


          import (

          "testProject/controllers"

          "github.com/astaxie/beego"

          )


          func init() {

              beego.Router("/", &controllers.MainController{})

          }

          然后在命令行里執行swagger generate spec -o ./swagger.json,執行完成后會在你工程的根目錄下生成一個swagger.json文件。這就是自動生成的接口文檔,上面內容生成的對應文件為:

          {

            "consumes": [

              "application/json",

              "application/xml"

            ],

            "produces": [

              "application/json",

              "application/xml"

            ],

            "schemes": [

              "http",

              "https"

            ],

            "swagger": "2.0",

            "info": {

              "description": "the purpose of this application is to provide an application\nthat is using plain go code to define an API\n\nThis should demonstrate all the possible comment annotations\nthat are available to turn go code into a fully compliant swagger 2.0 spec",

              "title": "testProject API.",

              "termsOfService": "there are no TOS at this moment, use at your own risk we take no responsibility",

              "contact": {

                "name": "John Dan",

                "email": "john.dan@example.com"

              },

              "version": "0.0.1"

            },

            "host": "localhost",

            "basePath": "/v1",

            "paths": {}

          }

          你可以在swagger Editor中查看接口文檔,它會有一定樣式,便于閱讀。上面生成的接口文檔如下圖所示:

          20190904141646688[1].png

          使用swagger:route定義路由信息

          swagger:route標記用來定義接口的路由信息,它會將路徑連接到方法,此操作獲取唯一id,該id在各個位置用作方法名稱。語法如下:swagger:route [method] [path pattern] [?tag1 tag2 tag3] [operation id]。


          屬性

          標記含義

          Consumes描述接口支持的特定的mime類型值,如果有多個,每個類型占據一行。支持的MIME類型有json,yaml,xml,txt,bin,urlform,multipartform

          Produces描述接口支持的特定的mime類型值,如果有多個,每個類型占據一行

          Schemes描述接口支持的特定協議類型,可能的值有http,https,ws,wss

          Responses響應狀態碼字典

          示例

          package controllers


          import (

          "github.com/astaxie/beego"

          )


          type MainController struct {

          beego.Controller

          }


          // Get serves the API for this get index page

          func (c *MainController) Get() {

          // swagger:route GET / users indexPage

          //

          // Show index page.

          //

          // This will show all available users by default.

          //

          //     Consumes:

          //     - application/json

          //

          //     Produces:

          //     - application/json

          //

          //     Schemes: http, https, ws, wss

          //

          //     Responses:

          //       default: Resp

          //     422: validationError

          c.Data["Website"] = "beego.me"

          c.Data["Email"] = "astaxie@gmail.com"

          c.TplName = "index.tpl"

          }

          20190904141837901[1].png

          使用swagger:response定義響應

          使用swagger:route可以定義響應的名稱,接著需要做的就是將這些響應名稱和具體的響應結果對應起來。用法:swagger:response [?response name]。語法中的response name就是你在定義swagger:route的時候,通過Response屬性設置的名字。

          示例

          package models

          // A Resp is an response that is used when the request returned.

          // swagger:response Resp

          type Resp struct {

          // The response information

          // in: body

          //

          Body struct{

          // Required: true

          Status bool        `json:"status"`

          // Required: true

          Code   string      `json:"code"`

          // Required: true

          Msg    string      `json:"msg"`

          // An optional field name to which this validation applies

          Data   interface{} `json:"data,omitempty"`

          }

          }


          // A ValidationError is an error that is used when the required input fails validation.

          // swagger:response validationError

          type ValidationError struct {

          // The error message

          // in: body

          Body struct {

          // The validation message

          //

          // Required: true

          Message string

          // An optional field name to which this validation applies

          FieldName string

          }

          }

          20190904141951707[1].png

          注意: 通過上圖可以看出,響應結構體必須嵌套在你之前定義的響應結果名稱之內。


          使用swagger:params定義參數信息

          上面已經定義了接口地址相關信息,接著定義接口的參數信息。用法:swagger:parameters [operationid1 operationid2],這里的operationid1,operationid2都是之前在定義router時確定的。例如某些接口可能會有相同的參數,我們就可以在這里使用它們operationid。


          屬性

          標記含義

          In在哪里找到參數,例如是在query中或者在path中,也可以是body

          Required描述參數是否必須,true表示必須

          示例

          package models

          // A Resp is an response that is used when the request returned.

          // swagger:response Resp

          type Resp struct {

          // The response information

          // in: body

          //

          Body struct{

          // Required: true

          Status bool        `json:"status"`

          // Required: true

          Code   string      `json:"code"`

          // Required: true

          Msg    string      `json:"msg"`

          // An optional field name to which this validation applies

          Data   interface{} `json:"data,omitempty"`

          }

          }


          // A ValidationError is an error that is used when the required input fails validation.

          // swagger:response validationError

          type ValidationError struct {

          // The error message

          // in: body

          Body struct {

          // The validation message

          //

          // Required: true

          Message string

          // An optional field name to which this validation applies

          FieldName string

          }

          }


          // swagger:parameters indexPage

          type RequestParam struct {

          // in: body

          //

          Body struct{

          // a Nickname is user nick name which is string

          // Required: true

          Nickname string `json:"nickname"`

          Password string `json:"password"`

          VerifyCode int `json:"verifyCode"`

          }

          }

          2019090414213550[1].png

          可以看到在使用swagger:parameters定義operation id為indexPage的接口路由時,也是使用定義響應結構體那種形式,通過內嵌的方式實現。


          使用swagger:strfmt定義格式化的字符串

          語法為:swagger:strfmt [name],默認的字符串格式名字有:


          uuid,uuid3,uuid4,uuid5

          email

          uri(absolute)

          hostname

          ipv4

          ipv6

          credit card

          isbn,isbn10,isbn13

          social security number

          hexcolor

          rgbcolor

          date

          date-time

          duration

          password

          custom string formats

          示例

          當我們把之前定義的請求參數,添加一個參數email,它的格式應該為郵件格式的字符串。那么可以這樣定義。

          // swagger:parameters indexPage

          type RequestParam struct {

          // in: body

          //

          Body struct {

          // a Nickname is user nick name which is string

          // Required: true

          Nickname   string `json:"nickname"`

          Password   string `json:"password"`

          VerifyCode int    `json:"verifyCode"`

          // swagger:strfmt email

          Email string `json:"email"`

          }

          }

          20190904142214340[1].pnghttps://blog.csdn.net/benben_2015/article/details/100538074

          golang govalidators包 驗證

          go validators用法詳解 對struct字段進行參數驗證

          golang一枚,業務中有對接口struct字段進行參數驗證的需求,為了練手,自己造了個go validators驗證器的輪子,代碼在github,使用的詳細方法寫到這里,也希望大家在使用過程遇到問題來這提問

          在編寫golang接口時,需要對接收到的struct字段內容進行驗證,比如


          type Student struct {

           Uid   int64

           Name  string

           Age   int64

           Sex   string

           Email string

          }

          我們需要對結構體內的字段進行驗證合法性:

          • Uid的值在某一個范圍內

          • Name值的長度在某一個范圍內

          • Sex的值符合男或女

          • Email格式正確等等

          go validators可以對數據進行基本驗證,也可高度定制.

          安裝方式如下

          go get github.com/smokezl/govalidators


          先來個簡單例子,通過golang的structTag來配置驗證器

          type Class struct {
              Cid       int64  `validate:"required||integer=10000,_"`
              Cname     string `validate:"required||string=1,5||unique"`
              BeginTime string `validate:"required||datetime=H:i"`}type Student struct {
              Uid          int64    `validate:"required||integer=10000,_"`
              Name         string   `validate:"required||string=1,5"`
              Age          int64    `validate:"required||integer=10,30"`
              Sex          string   `validate:"required||in=male,female"`
              Email        string   `validate:"email||user||vm"`
              PersonalPage string   `validate:"url"`
              Hobby        []string `validate:"array=_,2||unique||in=swimming,running,drawing"`
              CreateTime   string   `validate:"datetime"`
              Class        []Class  `validate:"array=1,3"`}


          1. required 判斷字段對應的值是否是對應類型的零值

          2. integer 表示字段類型是否是整數類型,如果integer后邊不接=?,?,那么表示只判斷是否是整數類型,如果后邊接=?,?,那么有四種寫法
            (1). integer=10 表示字段值 = 10
            (2). integer=_ ,10 表示字段值 <= 10,字段值最小值為字段對應類型的最小值(比如字段對應類型為int8,那么最小為?128),最大值為10
            (3). integer=10, _ 表示字段值 >= 10,字段值最小值為10,最大值為字段對應類型的最大值(比如字段對應類型為int8,那么最大為127)
            (4). integer=1,20 表示字段值 >=1 并且 <= 20

          3. array、string 同 integer,array=?,? 表示元素個數范圍,string=?,? 表示字符串長度范圍

          4. email 表示字段值是否是合法的email地址

          5. url 表示字段值是否是合法的url地址

          6. in 表示字段值在in指定的值中,比如 Hobby 字段中,in=swimming,running,drawing,表示 Hobby 字段的值,只能是swimming,running,drawing中的一個或多個

          7. datetime 表示字段值符合日期類型,如果datetime后邊不接=?,那么默認為Y-m-d H:i:s,否則驗證器會按照指定格式判斷,比如 datetime=Y-m、datetime=Y/m/d H:i:s等,可以是Y m d H i s 的隨意拼接

          8. unique 表示字段值唯一,比如 Hobby 字段的 unique,表示 Hobby 字段值唯一,Class 中,Cname 字段的 unique,表示 Cname 字段值唯一


          介紹了各驗證器的作用,現在來開始使用吧

          import (

              "fmt"

              "github.com/smokezl/govalidators"

          )


          validator := govalidators.New()

          student := &Student{

              Uid:          1234567,

              Name:         "張三1111",

              Age:          31,

              Sex:          "male1",

              Email:        "@qq.com",

              PersonalPage: "www.abcd.com",

              Hobby:        []string{"swimming", "singing"},

              CreateTime:   "2018-03-03 05:60:00",

              Class: []Class{

                  Class{

                      Cid:       12345678,

                      Cname:     "語文",

                      BeginTime: "13:00",

                  },

                  Class{

                      Cid:       22345678,

                      Cname:     "數學",

                      BeginTime: "13:00",

                  },

                  Class{

                      Cid:       32345678,

                      Cname:     "數學",

                      BeginTime: "13:60",

                  },

              },

          }

          errList := validator.Validate(student)

          if errList != nil {

              for _, err := range errList {

                  fmt.Println("err:", err)

              }

          }

          執行結果:

          err: Name should be betwween 1 and 5 chars long

          err: Age should be betwween 10 and 30

          err: Sex is not in params [male female]

          err: Email is not a email address

          err: PersonalPage is not a url

          err: Hobby is not in params [swimming running drawing]

          err: CreateTime is not a date time

          err: Cname is not unique

          err: BeginTime is not a date time

          有時候,我們不需要將錯誤全部收集到,而是只要其中一個有錯,那么就返回錯誤,可以用 LazyValidate 方法

          err := validator.LazyValidate(student)

          if err != nil {

              fmt.Println("err:", err)

          }

          執行結果:

          err: Name should be betwween 1 and 5 chars long

          我們還可以對報錯信息、email 正則、url 正則進行自定義,先看下各個驗證器可以自定義的參數
            1. 公共 Range 類型

            type Range struct {

                Min string //最小值,外部可設置,支持0-9數字和 _ 符號,會將值賦值給 Range.min

                Max string //最大值,外部可設置,支持0-9數字和 _ 符號,會將值賦值給 Range.max

                min string //最小值,比對使用,支持0-9數字和 _ 符號,接收 Range.Min 和 struct 中傳進來的值

                max string //最大值,比對使用,支持0-9數字和 _ 符號,接收 Range.Max 和 struct 中傳進來的值


            /**

             * 自定義范圍判斷錯誤 msg 格式,map 的 keys 有 lessThan,equal,atLeast,between 

             * 根據類型的不同,msg 文案也不同,[min] 表示 Range.min, [max] 表示 Range.max

             * var stringErrorMap = map[string]string{

             *   "lessThan": "[name] should be less than [max] chars long",

             *   "equal":    "[name] should be equal [min] chars long",

             *   "atLeast":  "[name] should be at least [min] chars long",

             *   "between":  "[name] should be betwween [min] and [max] chars long",

             * }

             * var numberErrorMap = map[string]string{

             *   "lessThan": "[name] should be less than [max]",

             *   "equal":    "[name] should be equal [min]",

             *   "atLeast":  "[name] should be at least [min]",

             *   "between":  "[name] should be betwween [min] and [max]",

             * }

             * var arrayErrorMap = map[string]string{

             *   "lessThan": "array [name] length should be less than [max]",

             *   "equal":    "array [name] length should be equal [min]",

             *   "atLeast":  "array [name] length should be at least [min]",

             *   "between":  "array [name] length should be betwween [min] and [max]",

             * }

             */

                RangeEMsg map[string]string

            }

            1. required

            type RequiredValidator struct {

                EMsg string //自定義錯誤 msg 格式,默認為 [name] is must required,[name] 表示屬性名,下同

            }

            1. string

            type StringValidator struct {

                EMsg  string //自定義錯誤 msg 格式,默認為 [name] is not a string

                Range        //涉及到判斷范圍(字符串長度、數組長度、數字大小)驗證器的公共屬性

            }

            1. integer

            type IntegerValidator struct {

                EMsg  string //自定義錯誤 msg 格式,默認為 [name] is not a integer

                Range        //涉及到判斷范圍(字符串長度、數組長度、數字大小)驗證器的公共屬性

            }

            1. array

            type ArrayValidator struct {

                EMsg  string //自定義錯誤 msg 格式,默認為 [name] is not a array/map/slice

                Range        //涉及到判斷范圍(字符串長度、數組長度、數字大小)驗證器的公共屬性

            }

            1. email

            type EmailValidator struct {

                EMsg string //自定義錯誤 msg 格式,默認為 [name] is not a email address

                Reg  string //自定義 email 正則

            }

            1. url

            type UrlValidator struct {

                EMsg string //自定義錯誤 msg 格式,默認為 [name] is not a url

                Reg  string //自定義 url 正則

            }

            1. in

            type InValidator struct {

                EMsg     string //自定義錯誤 msg 格式,默認為 [name] is not in params [args]

                TypeEMsg string //自定義類型錯誤 msg 格式,默認為 [name] type invalid

            }

            1. datetime

            type DateTimeValidator struct {

                EMsg   string //自定義錯誤 msg 格式,默認為 [name] is not a date time

                FmtStr string //自定義Y m d H i s 組合,默認為 Y-m-d H:i:s

            }

            1. unique

            type UniqueValidator struct {

                EMsg string //自定義錯誤 msg 格式,默認為 [name] is not unique

            }

            如果我們想把剛才的報錯信息,都改為中文,那么就可以對每個驗證器錯誤 msg 進行自定義

            validator := govalidators.New()

            validator.SetValidators(map[string]interface{}{

                "string": &govalidators.StringValidator{

                    Range: govalidators.Range{

                        RangeEMsg: map[string]string{

                            "between": "[name] 長度必須在 [min] 和 [max] 之間",

                        },

                    },

                },

                "integer": &govalidators.IntegerValidator{

                    Range: govalidators.Range{

                        RangeEMsg: map[string]string{

                            "between": "[name] 的值必須在 [min] 和 [max] 之間",

                        },

                    },

                },

                "in": &govalidators.InValidator{

                    EMsg: "[name] 的值必須為 [args] 中的一個",

                },

                "email": &govalidators.EmailValidator{

                    EMsg: "[name] 不是一個有效的email地址",

                },

                "url": &govalidators.UrlValidator{

                    EMsg: "[name] 不是一個有效的url地址",

                },

                "datetime": &govalidators.DateTimeValidator{

                    EMsg: "[name] 不是一個有效的日期",

                },

                "unique": &govalidators.UniqueValidator{

                    EMsg: "[name] 不是唯一的",

                },

            })

            errList := validator.Validate(student)

            if errList != nil {

                for _, err := range errList {

                    fmt.Println("err:", err)

                }

            }

            執行結果:

            err: Name 長度必須在 1 和 5 之間

            err: Age 的值必須在 10 和 30 之間

            err: Sex 的值必須為 [male female] 中的一個

            err: Email 不是一個有效的email地址

            err: PersonalPage 不是一個有效的url地址

            err: Hobby 的值必須為 [swimming running drawing] 中的一個

            err: CreateTime 不是一個有效的日期

            err: Cname 不是唯一的

            err: BeginTime 不是一個有效的日期

            如果現有的驗證器不夠用,還可以進行自定義,只需要滿足 ValidatorF 函數類型 或 Validator 接口就可以

            ValidatorF 類型

            type ValidatorF func(params map[string]interface{}, val reflect.Value, args ...string) (bool, error)

            Validator 接口

            type Validator interface {

                Validate(params map[string]interface{}, val reflect.Value, args ...string) (bool, error)

            }

            例子

            type UserValidator struct {

                EMsg string

            }


            func (self *UserValidator) Validate(params map[string]interface{}, val reflect.Value, args ...string) (bool, error) {

                fmt.Println("=====", "UserValidator")

                return true, nil

            }


            func userMethod(params map[string]interface{}, val reflect.Value, args ...string) (bool, error) {

                fmt.Println("=====", "userMethod")

                return true, nil

            }

            validator.SetValidators(map[string]interface{}{

                "user": &UserValidator{},

                "vm":   userMethod,

            })

            errList := validator.Validate(student)

            if errList != nil {

                for _, err := range errList {

                    fmt.Println("err:", err)

                }

            }

            struct 中,增加 user 和 vm 驗證

            Email        string   `validate:"email||user||vm"`

            執行結果:

            ===== UserValidator

            ===== userMethod

            來源https://www.cnblogs.com/yangxinpython/p/13161454.html

            golang decimal插件大數字處理

            package main
            
            import (
               "fmt"
            
               "github.com/shopspring/decimal"
            )
            
            func main() {
               price, _ := decimal.NewFromString("136.02")//獲取數字
               quantity := decimal.NewFromFloat(3)//
            
               fmt.Println(quantity)
               fee, _ := decimal.NewFromString(".035")
               taxRate, _ := decimal.NewFromString(".08875")
            
               subtotal := mul(price, quantity)
               preTax := mul(subtotal, add1(fee, decimal.NewFromFloat(1)))
               total := mul(preTax, add1(taxRate, decimal.NewFromFloat(1)))
               taxes := sub(total, preTax)
               taxRate = div(sub(total, preTax), preTax)
            
               fmt.Println("int,Subtotal:",int(subtotal))
               fmt.Println("float64,Subtotal:",float(subtotal))
            
               fmt.Println("Subtotal:", subtotal) // Subtotal: 408.06
               fmt.Println("Pre-tax:", preTax)    // Pre-tax: 422.3421
               fmt.Println("Taxes:", taxes)       // Taxes: 37.482861375
               fmt.Println("Total:", total)       // Total: 459.824961375
               fmt.Println("Tax rate:", taxRate)  // Tax rate: 0.08875
            }
            
            // 加法
            func add1(d1 decimal.Decimal, d2 decimal.Decimal) decimal.Decimal {
               return d1.Add(d2)
            }
            
            // 減法
            func sub(d1 decimal.Decimal, d2 decimal.Decimal) decimal.Decimal {
               return d1.Sub(d2)
            }
            
            // 乘法
            func mul(d1 decimal.Decimal, d2 decimal.Decimal) decimal.Decimal {
               return d1.Mul(d2)
            }
            
            // 除法
            func div(d1 decimal.Decimal, d2 decimal.Decimal) decimal.Decimal {
               return d1.Div(d2)
            }
            
            // int
            func int(d decimal.Decimal) int64{
               return d.IntPart()
            }
            
            // float
            func float(d decimal.Decimal) float64{
               f, exact := d.Float64()
               if !exact{
                  return f
               }
               return 0
            }


            PuTTY 新手使用教程

            PuTTY 經常用于 Windows 下連接管理遠程服務器。本文配合截圖介紹 PuTTY 的基礎用法及一些設置技巧.

            PuTTY 下載及相關工具包

            在下載頁提供有集成 PuTTY 及相關工具的完整安裝包

            putty.exeSSH 和 Telnet 客戶端(最常使用的)
            pscp.exeSCP 客戶端,命令行下通過 SSH 遠程拷貝文件
            psftp.exeSFTP 客戶端,命令行下的文件傳輸會話
            puttytel.exe一個單純 Telnet 客戶端
            plink.exePuTTY 后端的命令行工具
            pageant.exePuTTY、PSCP、Plink 的 SSH 認證代理
            puttygen.exeRSA、DSA、ECDSA 和 EdDSA 密鑰生成工具

            PuTTY 創建 SSH 會話連接

            運行 putty.exe,輸入服務器 IP 地址和端口(22 是 SSH 默認端口),選中 SSH 連接類型,設置連接會話名稱及點擊保存,點擊 Open 按鈕連接登錄。

            putty-tutorial-1[1].png

            首次連接會提示服務器指紋,選擇是或否?!笆恰睂⒈4嬷讣y,“否”則不保存。

            putty-tutorial-2[1].png

            之后輸入用戶名和密碼即可登錄服務器


            putty-tutorial-3[1].png


            如果需要注銷連接會話使用  Ctrl+d 快捷鍵。


            PuTTY 修改保存設置

            如果需要修改 PuTTY 默認設置,就選中修改 Default Setting


            putty-tutorial-4[1].png

            PuTTY 會話保持時間

            當與長時間沒數據傳輸時,PuTTY 會自動斷開連接。要避免該問題,可以在 Connection 選項 Seconds between keepalives 里開啟會話保持功能即可

            putty-tutorial-5[1].png

            PuTTY 復制粘貼文本

            在 SSH 會話窗口不能 Ctrl+C 這樣的快捷鍵(liunxCtrl+C 是終止命令執行),復制粘貼需要用鼠標。復制操作先用鼠標左鍵拖拽選中,然后單擊選中部分即可復制。


            PuTTY 窗口內容長度

            在 Windows 選項里修改 Lines of scrollback 數值可以調整PuTTY 會話窗口的長度

            putty-tutorial-6[1].png

            PuTTY 保存登錄用戶名

            如果登錄服務器用同一個用戶賬號,可以設置會話默認登錄用戶名,免去每次輸入麻煩。在 Connection 選項 Date 里設置。

            putty-tutorial-7[1].png

            PuTTY 使用私鑰登錄


            依次打開 Connection -> SSH -> Auth 選項,瀏覽選中私鑰文件,保存設置后即可使用密鑰方式登錄。

            putty-tutorial-8[1].png

            如果登錄提示下面錯誤,是因為 PuTTY 不支持 PEM 格式密鑰。需要用 puttygen.exe 程序轉換一下。

            運行 puttygen.exe,點擊 Load 導入私鑰文件,然后點擊 Save private key 另存為 ppk 后綴密鑰文件。

            putty-tutorial-9[1].png

            PuTTY 刪除會話配置信息

            除了在 PuTTY 選項里刪除連接會話外,也可以直接刪除軟件注冊表信息。

            到此,PuTTY 使用方法就介紹到這里了。關于文件傳輸,建議用支持圖形化界面的 SFTP 軟件,如 WinSCP、FileZilla 這些




            vmware使用教程及虛擬機安裝linux

            https://www.cnblogs.com/zln1021/p/9552722.html

            xftp的使用教程

            使用xftp來上傳,下載文件到linux主機

            首先,我們要下載一個xftp

            時已經安裝完成,點擊finish,打開軟件登錄SSH賬號,這里以默認的root賬號演示。

            1、關閉登陸彈出來的“會話”窗口:

            2、填入賬號信息:

            注意sftp連接需要前綴sftp再加上IP地址或域名(實列. sftp://www.voyageurimaginaire.com),然后是賬號和密碼;點擊連接。

            3、SSH安全警告(接受并保存,只在首次登陸提示):

            上傳下載功能:sftp客戶端跟普通的FTP一樣,拖動文件就可以了;而且中文界面也很方便。自定義編輯器:在Xftp界面中,工具 -> 選項 -> 高級 -> 編輯器路徑,選擇自

            定義編輯器的路徑就可以了


            在自定義編輯器中,保存文本,Xftp即自動上傳修改后的文檔。


            Xshell入門使用教程

            Xshell 是一個強大的遠程管理軟件,它支持TELNET,SSH 協議。Xshell可以在Windows下訪問遠端服務器、路由器、網絡機頂盒等,類似的常用軟件還有putty,以及Telnet等待。

            Xshell的幾個特點:

            • 可以保存密碼,注意安全,盡量不要保存,除非個人電腦。

            • 支持標簽,打開多個服務器時候很方便,點擊標簽切換。

            • 界面設計簡潔、人性,使用方便。


            Xshell下載安裝及基本使用方法:

            1、從網上搜索下載,注意別下載錯了。

            2、打開xshell。


            3、個性化設置。設置好,用起來更順手。經過這樣設置,以后使用事半功倍。其他地方,根據自己的喜好,可以進行相關設置。

            4、連接服務器或路由器。點擊打開。

            5、點擊左上角,新建

            6、填寫完,點擊確定。其他高級參數,有需要可以填寫。常用的主機或路由器,可以點擊身份驗證,填寫用戶名和密碼,這樣不需要輸入就可以直接登錄系統了。

            7、第一次連接會出現提示,如下圖。

            8、登錄成功,可以輸入相關命令,進行各種操作。

            xshell幾個常用命令以及注意事項:

            cd .. 回到上級目錄

            cd jennal.cn 進入jennal.cn目錄

            rm jennal.cn 刪除文件jennal.cn

            rm -rf 刪除目錄及其所包含的所有文件,高危命令,一定謹慎

            mkdir jennal.cn 創建目錄jennal.cn

            vi 查看/編輯文件 按 i進入編輯模式;按Esc鍵退出編輯模式。按:q退出不保存; 按:wq保存退出。




            << < 1 2 3 4 5 6 7 8 9 10 > >>

            Copyright www.voyageurimaginaire.com Rights Reserved葵花寶典教程.鄂icp2022001145號-1

            分享:

            支付寶

            微信

            精品一区二区三区无码毛片
          1. <tbody id="baor6"></tbody>

          2. <em id="baor6"><acronym id="baor6"><input id="baor6"></input></acronym></em>
            <strike id="baor6"></strike><li id="baor6"></li>
            <rp id="baor6"></rp>
            1. <em id="baor6"></em>
              <form id="baor6"></form>
              <nobr id="baor6"></nobr>

              <em id="baor6"><acronym id="baor6"><u id="baor6"></u></acronym></em>