Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 欧美日韩综合,成人免费一级毛片在线播放视频,久久婷婷精品国产电影网

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML編碼規范

          版規則

          縮進

          使用2個空格縮進

          <ul>
            <li>Fantastic</li>
            <li>Great</li>
          </ul>
          .example {
            color: blue;
          }

          大小寫

          只允許使用小寫。

          所有的代碼都用小寫字母:適用于元素名,屬性,屬性值(除了文本和CDATA), 選擇器,特性,特性值(除了字符串)。

          <!-- 不推薦 -->
          <A HREF="/">Home</A>
          <!-- 推薦 -->
          <img src="google.png"
          alt="Google">

          行為空格

          建議刪除行尾白空格。

          <!-- 不推薦 -->
          <p>What?  </p>
          <!-- 推薦 -->
          <p>Yes please.</p>

          常規Meta規則

          編碼

          如果沒有特殊需求,一般采用utf-8編碼。如果是cms站點,則遵守該站點的編碼規則。

          <!-- 網頁編碼 -->
          <meta charset="utf-8">

          注釋

          盡可能的去解釋你寫的代碼。說明該代碼包括什么、目的是什么、能做什么、為什么使用它等。

          注釋是否需要詳盡,取決于項目的復雜程度。

          一般單行注釋:

          <!-- col -->

          模塊間注釋:

          <!-- news -->
          <div class="news">
            <h2>News</h2>
            <p>...</p>
          </div>
          <!--/ news -->

          循環注釋:

          <ul>
            <!-- loop: new list -->
            <li>new's title 1</li>
            <li>new's title 2</li>
            <li>new's title 3</li>
            <li>new's title 4</li>
            <li>new's title 5</li>
            <!-- /loop: new list -->
          </ul>

          cms輸出注釋:

          <!-- cms: news list -->
          <ul>
            <li>new's title 1</li>
            <li>new's title 2</li>
            <li>new's title 3</li>
            <li>new's title 4</li>
            <li>new's title 5</li>
          </ul>
          <!-- /cms: news list -->

          Tab選項卡內容注釋:

          <!-- tab: news list -->
          <div class="tab"></div>
          <!-- /tab: news list -->

          常規HTML設計規則

          文檔類型

          使用html5文檔聲明,不再使用XHTML(application/xhtml+xml)。

          HTML5是目前所有HTML文檔類型中的首選:

          <!DOCTYPE html>

          HTML 的正確性

          編寫有效、正確的HTML代碼,否則很難達到性能上的提升。

          可以使用一些工具驗證你的代碼,如 W3C HTML validator

          HTML 的語義性

          根據HTML各個元素的用途而去使用它們。

          <!-- 不推薦 -->
          <div class="col">
            <div class="title">
          news</div>
            <p>list1</p>
            <p>list2</p>
            <p>list3</p>
          </div>
          <!-- 推薦 -->
          <div class="col">
            <h2 class="title">
          news</h2>
            <p>list1</p>
            <p>list2</p>
            <p>list3</p>
          </div>

          部分標簽說明:

          • div 主要用于布局,分割頁面的結構;
          • ul/ol 主要用于無序/有序列表;
          • dl/dt/dd 當頁面中出現第一行為類似標題/簡述,然后下面為詳細描述的內容時應該使用該標簽;
          • span 沒有特殊的意義,可以用作排版的輔助,然后在css中定義span;
          • h1-h6 標題, 根據重要性依次遞減;
          • h1 最重要的標題;
          • label 使表單更有親和力而且能輔助表單排版;

          不推薦使用的標簽:

          • font 文字的外觀,大小和顏色;
          • u 文本下劃線;
          • center 居中對齊;
          • s 刪除線;
          • strike 刪除線;
          • noframes 無視框時的內容;
          • iframe 定義嵌入視圖;
          • isindex 不建議使用(可搜尋,使用input代替);
          • dir 目錄式列舉;
          • menu 菜單列表;
          • basefont 定義基本字體;
          • applet 定義java程序;
          • frame 定義個別視框;
          • frameset 視框格式總定義;

          多媒體元素降級處理

          給多媒體元素,比如canvas、videos、 images增加alt屬性,提高可用性(特別是常用的img標簽,盡可量得加上alt屬性,提供圖片的描述信息)。

          <!-- 不推薦 -->
          <img src="world.jpg">
          <!-- 推薦 -->
          <img src="world.jpg"
          alt="our world images">

          type屬性

          在樣式表和腳本的標簽中忽略type屬性。

          HTML5默認type為text/css和text/javascript類型,所以沒必要指定。即便是老瀏覽器也是支持的。

          <!-- 不推薦 -->
          <link rel="stylesheet"
           href="//www.google.com/css/maia.css"
           type="text/css">
          <script src="
           //www.google.com/
           js/gweb/analytics/autotrack.js"
           type="text/javascript">
           </script>
          <!-- 推薦 -->
          <link rel="stylesheet"
           href="//www.google.com/css/maia.css">
          <script src="
           //www.google.com/
           js/gweb/analytics/autotrack.js">
           </script>

          HTML代碼格式規則

          每個塊元素、列表元素或表格元素都獨占一行,每個子元素都相對于父元素進行縮進。按設計稿劃分模塊,盡量使頁面模塊化,模塊與模塊之前要有清晰的注釋。

          如上面頁面框架,推薦寫法:

          <!-- hader -->
          <div class="header">header</div>
          <!-- /hader -->
          <!-- nav -->
          <div class="nav">nav</div>
          <!-- /nav -->
          <!-- main -->
          <div class="main">
            <!-- container -->
            <div class="container">
              <!--news-->
              <div class="news">
                <h2>news<h2>
                <p>...</p>
              </div>
              <!--news-->
            </div>
            <!--/container-->
            <!--sidebar-->
            <div class="sidebar">
          sidebar</div>
            <!--sidebar-->
          </div>
          <!--/main-->
          <!--footer-->
          <div class="footer">
          footer</div>
          <!--/footer-->

          HTML與SEO

          頁面良好層次

          保證整個頁面在未加載樣式表時仍有較好的層次清晰的頁面結構。

          <!-- 不推薦 -->
          <div class="logo">My Site</div>
          <div class="nav">
            <a href="#">Home</a>
            <a href="#">News</a>
            <a href="#">Mobile</a>
          </div>
          <div class="news">
            <div>News</div>
            <a href="#">
          news list 1</a>
            <a href="#">
          news list 2</a>
            <a href="#">
          news list 3</a>
          </div>
          <!-- 推薦 -->
          <h1 class="logo">My Site</h1>
          <ul class="nav">
            <li><a href="#">
          Home</a></li>
            <li><a href="#">
          News</a></li>
            <li><a href="#">
          Mobile</a></li>
          </ul>
          <div class="news">
            <h2>News</h2>
            <ul>
              <li><a href="#">
          news list 1</a>
          </li>
              <li><a href="#">
          news list 2</a>
          </li>
              <li><a href="#">
          news list 3</a>
          </li>
            </ul>
          </div>

          權重標簽使用

          H標簽使用

          • h1 權重高,體現當前網頁中相對比較重要的信息,但不宜過多,建議一個頁面只放一個;
          • h2 可以做副標題;
          • h3 可以做新聞列表;
          • h4-h6 可做相關新聞的列表標簽屬性完整;

          strong、b使用

          將需要加粗的文字使用b標簽來顯示。

          將需要強調的文字(主要指包含關鍵詞的信息)使用strong標簽來強調主要內容。

          注:b是粗體標簽,屬于實體標簽,它所包圍的字符將被設為bold(粗體);strong 是加重語氣標簽,屬于邏輯標簽,它的作用是加強字符語氣。

          標簽屬性使用

          在很多情況下,a都要使用title來說明該鏈接的相關說明或目的意義。

          例如:當使用overflow隱藏掉a中的溢出文字時,該a中的title是必不可少的,它可以告訴用戶被隱藏掉的文字內容是什么;又或者當一個圖片型鏈接出現時,該a中的title同樣是必不可少的,它可以告訴用戶這個圖片鏈接是做什么用的。

          注:僅在img里添加alt標簽在火狐提示文字是出不來的,alt是圖片加載失敗或未加載完全時顯示出來的提示文字,要想鼠標移上去顯示提示信息應該用title,嚴謹的寫法是img里加入alt和title這兩個標簽。

          精簡代碼

          代碼保持精簡,最優化,這樣搜索引擎才更喜歡。

          算機網絡中的OSI七層模型

          計算機網絡中的OSI(Open Systems Interconnection)七層模型是一種理論框架,用于描述計算機網絡中數據通信的過程。OSI模型將計算機網絡通信過程劃分為七個層次,每個層次都有其特定的功能和協議。這種分層結構有助于研究和理解計算機網絡中的通信原理。以下是OSI七層模型的各個層次及其主要功能:

          應用層是OSI模型的第七層,也是網絡應用程序和網絡協議之間的接口。應用層主要負責為用戶提供各類應用服務,如文件傳輸、電子郵件、Web瀏覽等。

          表示層是OSI模型的第六層,主要負責處理在網絡中傳輸的數據的表示方式,如數據加密、解密、壓縮、解壓縮等。表示層確保了不同系統之間的數據兼容性。

          會話層是OSI模型的第五層,主要負責建立、維護和終止應用程序之間的通信會話。會話層提供了數據交換的同步和確認機制。

          傳輸層是OSI模型的第四層,主要負責在源主機和目標主機之間提供可靠的、端到端的數據傳輸服務。傳輸層通過分段、封裝和重組數據來實現可靠的數據傳輸。常見的傳輸層協議包括TCP(傳輸控制協議)和UDP(用戶數據報協議)。

          網絡層是OSI模型的第三層,主要負責將數據包從源主機路由到目標主機。網絡層主要負責邏輯尋址、路由選擇和分組轉發。常見的網絡層協議包括IP(互聯網協議)和ICMP(互聯網控制報文協議)。

          數據鏈路層是OSI模型的第二層,主要負責將網絡層傳來的數據包封裝成幀(Frame),并在同一局域網內進行傳輸。數據鏈路層主要負責物理尋址、數據成幀、錯誤檢測和流量控制。常見的數據鏈路層協議包括以太網(Ethernet)、令牌環(Token Ring)和無線局域網(Wi-Fi)等。

          物理層是OSI模型的第一層,主要負責在物理介質上實現比特流的透明傳輸。物理層主要關注硬件接口、電氣特性、光纖、無線傳輸等方面的問題。

          OSI七層模型提供了一個通用的框架,幫助研究和理解計算機網絡中的通信原理。實際應用中,我們通常使用TCP/IP四層模型,它包括了應用層、傳輸層、網絡層和鏈路層,與OSI模型有一定的對應關系。

          HTML框架的必要性

          HTML框架進行分層設計的主要原因是為了提高代碼的可讀性、可維護性和可重用性。將HTML框架分層可以提高整體項目的結構和邏輯,便于開發者更好地理解和修改代碼。分層設計具有以下優點:

          1. 提高可讀性:通過將HTML框架劃分為不同的層次,可以使代碼結構更清晰,有助于開發者快速理解代碼的功能。
          2. 便于維護:分層設計有助于將功能模塊化,這樣可以方便地修改或替換某個模塊,而不會影響其他部分的代碼。這有助于提高項目的可維護性。
          3. 可重用性:將HTML框架分層可以將公共部分提取為可重用的組件,這樣可以在不同項目中重復使用這些組件,提高開發效率。
          4. 適應性:分層設計可以讓HTML框架更容易適應不同的設備和屏幕尺寸,提高項目的兼容性。
          5. 便于協作:在大型項目中,通常會有多個開發者參與。通過分層設計,開發者可以專注于自己的模塊,減少代碼沖突和溝通成本。

          HTML框架的組成

          HTML框架包括Application層``middleware層``route層``codec層``transport層 Application層 應用層通常包括與業務邏輯相關的代碼,如Web應用程序的控制器(Controller)、視圖(View)和模型(Model)。應用層的主要作用是處理用戶請求并返回相應的響應。

          Middleware層 中間件層是介于應用層和底層框架之間的一層,負責處理一些通用的功能,如身份驗證、授權、緩存、日志記錄等。中間件層有助于將業務邏輯與通用功能分離,使得應用層更加簡潔和易于維護。

          Route層 路由層負責處理HTTP請求的URL和HTTP方法(如GET、POST等),將請求分發到相應的控制器和方法。路由層的主要作用是根據URL映射來定位具體的功能代碼。

          Codec層 編解碼層負責處理數據的編碼和解碼。在Web開發中,編碼和解碼通常涉及到HTML、CSS、JavaScript等前端技術的處理,以及JSON、XML等數據交換格式的處理。編解碼層的主要作用是將數據轉換為特定的格式,以便在不同層之間進行傳輸和處理。

          Transport層 傳輸層負責處理底層的網絡通信,如TCP、UDP等協議的使用。在Web開發中,傳輸層通常涉及到HTTP協議的處理,包括請求和響應的創建、發送和接收。傳輸層的主要作用是確保數據的可靠傳輸和在網絡中的正確路由。

          這些層次在實際應用中可能因框架和場景的不同而有所差異。但是,從您提供的描述來看,它們分別負責處理Web應用程序中的不同功能,共同構成了一個完整的Web開發框架。

          HTML框架和服務端客戶端之間的通信對比

          Application層應用層設計

          應用層設計主要是設置各種接口,用于路由使用。

          例如在字節后端進階版中的大項目中的注冊接口。

          /douyin/user/register/ - 用戶注冊接口

          新用戶注冊時提供用戶名,密碼,昵稱即可,用戶名需要保證唯一。創建成功后返回用戶 id 和權限token.

          接口類型

          POST

          接口定義

          go復制代碼syntax = "proto2";
          package douyin.core;
          
          message douyin_user_register_request {
            required string username = 1; // 注冊用戶名,最長32個字符
            required string password = 2; // 密碼,最長32個字符
          }
          
          message douyin_user_register_response {
            required int32 status_code = 1; // 狀態碼,0-成功,其他值-失敗
            optional string status_msg = 2; // 返回狀態描述
            required int64 user_id = 3; // 用戶id
            required string token = 4; // 用戶鑒權token
          }
          
          go復制代碼func Register(username, password string) (id int64, token int64, err error) {
             if len(username) > 32 {
                return 0, 0, errors.New("用戶名過長,不可超過32位")
             }
             if len(password) > 32 {
                return 0, 0, errors.New("密碼過長,不可超過32位")
             }
             // 先查布隆過濾器,不存在直接返回錯誤,降低數據庫的壓力
             if userNameFilter.TestString(username) {
                return 0, 0, errors.New("用戶名已經存在!")
             }
             //雪花算法生成token
             node, err := snowflake.NewNode(1) //這里的userIdInt64就是 User.Id(主鍵)
             if err != nil {
                log.Println("雪花算法生成id錯誤!")
                log.Println(err)
             }
             token1 := node.Generate().Int64()
             tokenStr := strconv.FormatInt(token1, 10)
             user := domain.User{}
             // 再查緩存
             data, err := dao.RedisClient.Get(context.Background(), tokenStr).Result()
             if err == redis.Nil {
                fmt.Println("token does not exist")
             } else if err != nil {
                fmt.Println("Error:", err)
             } else {
                num, err := strconv.ParseInt(data, 10, 64)
                if err != nil {
                   fmt.Println("Error:", err)
                   return num, 0, err
                }
          
                return num, token1, nil
             }
             //在查數據庫
             user = domain.User{}
             dao.DB.Model(&domain.User{}).Where("name = ?", username).Find(&user)
             if user.Id != 0 {
                return 0, 0, errors.New("用戶已存在")
             }
             user.Name = username
             // 加密存儲用戶密碼
             user.Salt = randSalt()
             buf := bytes.Buffer{}
             buf.WriteString(username)
             buf.WriteString(password)
             buf.WriteString(user.Salt)
             pwd, err1 := bcrypt.GenerateFromPassword(buf.Bytes(), bcrypt.MinCost)
             if err1 != nil {
                return 0, 0, err
             }
             user.Pwd = string(pwd)
          
             //存在mysql里邊
             dao.DB.Model(&domain.User{}).Create(&user)
             //再把用戶id作為鍵 用戶的所有信息作為值存在其中
             //用戶信息的緩存是 保存在redis中 一個以id為鍵 user json為值
             jsonuser, err1 := MarshalUser(user)
             if err1 != nil {
                fmt.Println("err1", err1)
                return 0, 0, err1
             }
             err = dao.RedisClient.Set(context.Background(), strconv.FormatInt(user.Id, 10), jsonuser, 0).Err()
             if err != nil {
                fmt.Println("err", err)
                return 0, 0, err
             }
             // 布隆過濾器中加入新用戶
             userIdFilter.AddString(strconv.FormatInt(user.Id, 10))
             userNameFilter.AddString(username)
             return user.Id, token1, nil
          }
          

          本接口注冊功能實現:把所有信息存在mysql里邊當然redis里邊也存在這些信息,當然username也存在了布容過濾器中去,當接收到用戶的username的時候我們現在布容過濾器中先查詢是否存在如果存在則直接返回err,不存在然后再在redis里邊查詢,因為redis相比于mysql是更為輕量級的所以我們要先在redis里邊進行查,如果查不到再進mysql里邊查去,查不到說明沒有注冊過,可以注冊。

          命名規范

          遵循命名規范原則。

          Middleware層中間件

          gin框架里的中間件分為全局中間件,局部中間件。那么什么是中間件?中間件是為應用提供通用服務和功能的軟件。數據管理、應用服務、消息傳遞、身份驗證和 API 管理通常都要通過中間件。在gin框架里,就是我們的所有API接口都要經過我們的中間件,我們可以在中間件做一些攔截處理。

          中間件常用模型

          全局中間件

          這個是在服務啟動就開始注冊,全局意味著所有API接口都會經過這里。Gin的中間件是通過Use方法設置的,它接收一個可變參數,所以我們同時可以設置多個中間件。

          首先定義如下

          go復制代碼// 1.創建路由
          r := gin.Default()  //默認帶Logger(), Recovery()這兩個內置中間件
          r:= gin.New()      //不帶任何中間件
          // 注冊中間件  
          r.Use(MiddleWare())
          r.Use(MiddleWare2())
          

          注意的是

          gin.Default()默認使用了Logger和Recovery中間件,其中:Logger中間件將日志寫入gin.DefaultWriter,即使配置了GIN_MODE=release。Recovery中間件會recover任何panic。如果有panic的話,會寫入500響應碼。如果不想使用上面兩個默認的中間件,可以使用gin.New()新建一個沒有任何默認中間件的路由。

          go復制代碼// 定義中間
          func MiddleWare() gin.HandlerFunc {
              return func(c *gin.Context) {
                  t := time.Now()
                  fmt.Println("中間件開始執行了")
                  // 設置變量到Context的key中,可以通過Get()取
                  c.Set("request", "這是中間件設置的值")
                  status := c.Writer.Status()
                  fmt.Println("中間件執行完畢", status)        
                  t2 := time.Since(t)
                  fmt.Println("time:", t2)
              }
          }
          

          然后啟動我們的服務,訪問任意一個接口可以看到輸出如下

          這是請求先到了中間件,然后在到我們的API接口。在中間件里可以設置變量到Context的key中,然后在我們的API接口取值。

          go復制代碼        r.GET("/", func(c *gin.Context) {
                      // 取值
                      req, _ := c.Get("request")
                      fmt.Println("request:", req)
                      // 頁面接收
                      c.JSON(200, gin.H{"request": req})
                  })
          

          這時候在訪問就可以看到中間件設置的值是

          next方法是在中間件里面使用,這個是執行后續中間件請求處理的意思(含沒有執行的中間件和我們定義的GET方法處理,如果連續注冊幾個中間件則會是按照順序先進后出的執行,遇到next就去執行下一個中間件里的next前面方法。

          go復制代碼        // 執行函數
                  c.Next()
                  // 中間件執行完后續的一些事情
          

          局部中間件

          局部中間件意味著部分接口才會生效,只在局部使用,這時候訪問http:127.0.0.1:8000/ 才會看到中間件的日志打印,其他API接口則不會出現。

          go復制代碼   //局部中間件使用
              r.GET("/", MiddleWare(), func(c *gin.Context) {
                  // 取值
                  req, _ := c.Get("request")
                  fmt.Println("request:", req)
                  // 頁面接收
                  c.JSON(200, gin.H{"request": req})
              })
          

          gin內置中間件

          go復制代碼
          func BasicAuth(accounts Accounts) HandlerFunc
          
          func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc
          
          func Bind(val interface{}) HandlerFunc
          
          func ErrorLogger() HandlerFunc
          
          func ErrorLoggerT(typ ErrorType) HandlerFunc
          
          func Logger() HandlerFunc
          
          func LoggerWithConfig(conf LoggerConfig) HandlerFunc
          
          func LoggerWithFormatter(f LogFormatter) HandlerFunc
          
          func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc
          
          func Recovery() HandlerFunc
          
          func RecoveryWithWriter(out io.Writer) HandlerFunc
          
          func WrapF(f http.HandlerFunc) HandlerFunc
          
          func WrapH(h http.Handler) HandlerFunc
          

          總結

          通過自定義中間件,我們可以很方便的攔截請求,來做一些我們需要做的事情,比如日志記錄、授權校驗、各種過濾等等。

          route層路由層

          Gin 是一個標準的 Web 服務框架,遵循 Restful API 接口規范,其路由庫是基于 httproute 實現的。

          本節將從 Gin 路由開始,詳細講述各種路由場景下,如何通過 Gin 來實現。

          基本路由

          1. GET:用于處理從客戶端發起的HTTP GET請求。GET請求用于從服務器獲取數據,不應對服務器上的數據進行更改。例如,獲取用戶信息、獲取文章列表等。
          2. POST:用于處理從客戶端發起的HTTP POST請求。POST請求通常用于向服務器發送數據,用于創建新的資源或更新已有的資源。例如,用戶注冊、發布文章、更新用戶信息等。
          3. PUT:用于處理從客戶端發起的HTTP PUT請求。PUT請求通常用于更新服務器上的資源。例如,更新用戶信息、更新文章內容等。
          4. DELETE:用于處理從客戶端發起的HTTP DELETE請求。DELETE請求通常用于從服務器刪除資源。例如,刪除用戶賬戶、刪除文章等。
          5. PATCH:用于處理從客戶端發起的HTTP PATCH請求。PATCH請求通常用于對服務器上的資源進行部分更新。例如,更新用戶的部分信息、更新文章標題等。
          6. OPTIONS:用于處理從客戶端發起的HTTP OPTIONS請求。OPTIONS請求用于獲取服務器支持的HTTP方法。例如,跨域資源共享(CORS)場景。
          7. HEAD:用于處理從客戶端發起的HTTP HEAD請求。HEAD請求類似于GET請求,但不返回響應體。主要用于獲取響應頭信息。例如,檢查資源是否存在,但不需要獲取資源內容。
          8. ANY:用于處理任何HTTP方法(GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)的請求。適用于處理多種HTTP方法的情況。
          9. CONNECT:用于處理從客戶端發起的HTTP CONNECT請求。CONNECT請求通常用于建立客戶端與服務器之間的隧道,用于代理或其他場景。
          10. TRACE:用于處理從客戶端發起的HTTP TRACE請求。TRACE請求用于測試或診斷網絡連接。服務器應當返回原始的請求信息,以便客戶端可以檢查中間代理或防火墻是否進行了修改。

          示例

          字節大項目注冊接口

          go復制代碼syntax = "proto2";
          package douyin.core;
          
          message douyin_user_register_request {
            required string username = 1; // 注冊用戶名,最長32個字符
            required string password = 2; // 密碼,最長32個字符
          }
          
          message douyin_user_register_response {
            required int32 status_code = 1; // 狀態碼,0-成功,其他值-失敗
            optional string status_msg = 2; // 返回狀態描述
            required int64 user_id = 3; // 用戶id
            required string token = 4; // 用戶鑒權token
          }
          
          go復制代碼func Register(c *gin.Context) {
          
             username := c.Query("username")
             password := c.Query("password")
             id, token, err := service.Register(username, password)
             if err != nil {
                c.JSON(http.StatusOK, domain.Response{StatusCode: 1, StatusMsg: err.Error()})
             } else {
          
                c.JSON(http.StatusOK, domain.UserLoginResponse{
                   //可以直接去掉
                   Response: domain.Response{StatusCode: 0},
                   Id:       id,
                   Token:    token,
                })
             }
          }
          

          go復制代碼package main
          
          import (
             "github.com/gin-gonic/gin"
             "github.com/goTouch/TicTok_SimpleVersion/controller"
          )
          
          func initRouter(r *gin.Engine) {
             // public directory is used to serve static resources
             r.Static("/static", "./public")
          
             apiRouter := r.Group("/douyin")
          
             // basic apis
             //controller.VerifyToken,
             apiRouter.POST("/user/", controller.UserInfo)
             apiRouter.POST("/user/register/", controller.LoginLimit, controller.Register)
             apiRouter.POST("/user/login/", controller.LoginLimit, controller.Login)
             }
          

          codec層

          在Web開發中,編碼和解碼通常涉及到HTML、CSS、JavaScript等前端技術的處理,以及JSON、XML等數據交換格式的處理。編解碼層的主要作用是將數據轉換為特定的格式,以便在不同層之間進行傳輸和處理。

          示例

          在postman中的示例 json

          xml

          html復制代碼{"status_code":1,"status_msg":"redis: nil"}
          {"status_code":2,"status_msg":"no multipart boundary param in Content-Type"}
          
          Text復制代碼{"status_code":1,"status_msg":"redis: nil"}
          {"status_code":2,"status_msg":"no multipart boundary param in Content-Type"}
          
          Auto復制代碼{
              "status_code": 1,
              "status_msg": "redis: nil"
          }{
              "status_code": 2,
              "status_msg": "no multipart boundary param in Content-Type"
          }
          
          

          transport層傳輸層

          傳輸層負責處理底層的網絡通信,如TCP、UDP等協議的使用。在Web開發中,傳輸層通常涉及到HTTP協議的處理,包括請求和響應的創建、發送和接收。傳輸層的主要作用是確保數據的可靠傳輸和在網絡中的正確路由。

          golang語言中net/http這個庫中的conn 他是BIO自帶阻塞

          1. BIO (Blocking I/O)

          同步阻塞I/O模式,數據的讀取寫入必須阻塞在一個線程內等待其完成。

          1.1 傳統 BIO

          BIO通信(一請求一應答)模型圖如下(圖源網絡,原出處不明):

          采用 BIO 通信模型 的服務端,通常由一個獨立的 Acceptor 線程負責監聽客戶端的連接。我們一般通過在 while(true) 循環中服務端會調用 accept() 方法等待接收客戶端的連接的方式監聽請求,請求一旦接收到一個連接請求,就可以建立通信套接字在這個通信套接字上進行讀寫操作,此時不能再接收其他客戶端連接請求,只能等待同當前連接的客戶端的操作執行完成, 不過可以通過多線程來支持多個客戶端的連接,如上圖所示。

          如果要讓 BIO 通信模型 能夠同時處理多個客戶端請求,就必須使用多線程(主要原因是 socket.accept()、 socket.read()、 socket.write() 涉及的三個主要函數都是同步阻塞的),也就是說它在接收到客戶端連接請求之后為每個客戶端創建一個新的線程進行鏈路處理,處理完成之后,通過輸出流返回應答給客戶端,線程銷毀。這就是典型的 一請求一應答通信模型 。我們可以設想一下如果這個連接不做任何事情的話就會造成不必要的線程開銷,不過可以通過 線程池機制 改善,線程池還可以讓線程的創建和回收成本相對較低。使用FixedThreadPool 可以有效的控制了線程的最大數量,保證了系統有限的資源的控制,實現了N(客戶端請求數量):M(處理客戶端請求的線程數量)的偽異步I/O模型(N 可以遠遠大于 M),下面一節"偽異步 BIO"中會詳細介紹到。

          我們再設想一下當客戶端并發訪問量增加后這種模型會出現什么問題?

          程是寶貴的資源,線程的創建和銷毀成本很高,除此之外,線程的切換成本也是很高的。尤其在 Linux 這樣的操作系統中,線程本質上就是一個進程,創建和銷毀線程都是重量級的系統函數。如果并發訪問量增加會導致線程數急劇膨脹可能會導致線程堆棧溢出、創建新線程失敗等問題,最終導致進程宕機或者僵死,不能對外提供服務。 golang實現BIO

          NIO

          NIO: NIO是一種同步非阻塞IO, 基于Reactor模型來實現的。其實相當于就是一個線程處理大量的客戶端的請求,通過一個線程輪詢大量的channel,每次就獲取一批有事件的channel,然后對每個請求啟動一個線程處理即可。這里的核心就是非阻塞,就那個selector一個線程就可以不停輪詢channel,所有客戶端請求都不會阻塞,直接就會進來,大不了就是等待一下排著隊而已。這里面優化BIO的核心就是,一個客戶端并不是時時刻刻都有數據進行交互,沒有必要死耗著一個線程不放,所以客戶端選擇了讓線程歇一歇,只有客戶端有相應的操作的時候才發起通知,創建一個線程來處理請求。
          ————————————————
          NIO:模型圖

          Reactor模型:

          NIO核心組件詳細講解

          學習NIO先來搞清楚一些相關的概念,NIO通訊有哪些相關組件,對應的作用都是什么,之間有哪些聯系?

          多路復用機制實現Selector

          首先我們來了解下傳統的Socket網絡通訊模型。

          傳統Socket通訊原理圖

          為什么傳統的socket不支持海量連接

          每次一個客戶端接入,都是要在服務端創建一個線程來服務這個客戶端的,這會導致大量的客戶端的時候,服務端的線程數量可能達到幾千甚至幾萬,幾十萬,這會導致服務器端程序負載過高,不堪重負,最終系統崩潰死掉。

          • 接著來看下NIO是如何基于Selector實現多路復用機制支持的海量連接。

          NIO原理圖

          多路復用機制是如何支持海量連接

          NIO的線程模型 對Socket發起的連接不需要每個都創建一個線程,完全可以使用一個Selector來多路復用監聽N多個Channel是否有請求,該請求是對應的連接請求,還是發送數據的請求,這里面是基于操作系統底層的Select通知機制的,一個Selector不斷的輪詢多個Channel,這樣避免了創建多個線程,只有當莫個Channel有對應的請求的時候才會創建線程,可能說1000個請求, 只有100個請求是有數據交互的, 這個時候可能server端就提供10個線程就能夠處理這些請求。這樣的話就可以避免了創建大量的線程。

          NIO如何通過Buffer來緩沖數據的

          NIO中的Buffer是個什么東西 ?

          學習NIO,首當其沖就是要了解所謂的Buffer緩沖區,這個東西是NIO里比較核心的一個部分,一般來說,如果你要通過NIO寫數據到文件或者網絡,或者是從文件和網絡讀取數據出來此時就需要通過Buffer緩沖區來進行。Buffer的使用一般有如下幾個步驟:

          寫入數據到Buffer,調用flip()方法,從Buffer中讀取數據,調用clear()方法或者compact()方法。

          Buffer中對應的Position, Mark, Capacity,Limit都啥?

          capacity: 緩沖區容量的大小,就是里面包含的數據大小。
          limit: 對buffer緩沖區使用的一個限制,從這個index開始就不能讀取數據了。
          position: 代表著數組中可以開始讀寫的index, 不能大于limit。
          mark: 是類似路標的東西,在某個position的時候,設置一下mark,此時就可以設置一個標記,后續調用reset()方法可以把position復位到當時設置的那個mark上去,把position或limit調整為小于mark的值時,就丟棄這個mark。如果使用的是Direct模式創建的Buffer的話,就會減少中間緩沖直接使用的是DirectorBuffer來進行數據的存儲。
          ————————————————

          如何通過Channel和FileChannel讀取Buffer數據寫入磁盤的

          NIO中,Channel是什么?

          Channel是NIO中的數據通道,類似流,但是又有些不同,Channel即可從中讀取數據,又可以從寫數據到通道中,但是流的讀寫通常是單向的。Channel可以異步的讀寫。Channel中的數據總是要先讀到一個Buffer中,或者從緩沖區中將數據寫到通道中。

          FileChannel的作用是什么 Buffer有不同的類型,同樣Channel也有好幾個類型。 FileChannel,DatagramChannel,SocketChannel,ServerSocketChannel。這些通道涵蓋了UDP 和 TCP 網絡IO,以及文件IO。而FileChannel就是文件IO對應的管道, 在讀取文件的時候會用到這個管道。 golang的NIO

          TML標簽

          基本標簽

          HTML頁面中內容是由HTML標簽組織起來的,如頁面中的文本、圖像、Flash視頻文件等都是通過HTML標簽合理地顯示在頁面的各個位置。



          1 標題標簽<h1>~<h6>

          標題標簽表示一段文字的標題(主題),并且支持多層次的內容結構。HTNL.共提供了6級標題,分別為<h1>~<h6>,并賦予了標題一定的外觀,所有標題字體加粗,其中山<h1>字號最大,<h6>字號最小.


          2.圖像標簽<img>

          在網頁中常用的圖像格式有4種,即JPG、GIF、BMP.PNG,其中使用比較多的是JPG、GIF和PNG,大多數瀏覽器都可以顯示這些圖像。


          顯示圖像的語法:

          < img src="ur1" alt="文本" width="x" height="y"/>


          在語法中:

          a、SrC屬性:表示顯示圖像的地址。

          b、alt屬性:指定圖像的替代文本,當圖像無法顯示時(如圖片路徑錯誤或網速太慢等)替代顯示的文本,這樣,即使圖像無法顯示,用戶還可以看到網頁丟失的信息,所以為頁面上的圖像都加上替換文本屬性是個好習慣,這樣有助于更好地顯示信息,并且對于那些使用純文本瀏覽器的人來說是非常有幫助的。

          c、width屬性:表示圖像寬度.

          d、height屬性:表示圖像高度。


          3.段落標簽<p>

          顧名思義,段落標簽表示將一段文字組成一系列段落內容,這樣做的目的是內容應用某些格式和布局,使各個段落的邏輯更清晰明了。在HTML文檔中,段落通過<p>標簽定義。段落標簽<p>表示段落的開始,</p >表示段落的結束。


          4.換行標簽<br/>

          在希望不產生一個新段落的情況下進行換行,則使用<br>標簽。<br>是一個空的HTML標簽,由于關閉標簽沒有任何意義,因此它沒有結束標簽。


          注意:

          使用<b>和<br>的結果一樣,在XHTML以及未來的HTML版本中,根據W3C規范,不允許使用沒有結束標簽的HTML元素,因此使用<br>頁面更規范,有更長遠的保障。


          5.水平線標簽<hr/>

          水平線標簽表示一條水平線,注意該標簽與<br>標簽一樣,沒有結束標簽,直接使用<hr/>表示標簽的開始和結束。

          使用以上講解的基本標簽,就可以進行網頁內容排版了。


          主站蜘蛛池模板: 国产高清一区二区三区视频| 中文字幕无码免费久久9一区9| 国偷自产Av一区二区三区吞精| 91久久精品午夜一区二区| 精品一区二区三区在线观看l| 四虎一区二区成人免费影院网址 | 亚洲永久无码3D动漫一区| 国产未成女一区二区三区| 免费萌白酱国产一区二区三区| 国产精品一级香蕉一区| 亚洲国产日韩一区高清在线 | 亚洲男女一区二区三区| 国产成人高清视频一区二区| 在线观看国产一区亚洲bd| 亚洲综合无码一区二区三区| 无码日韩精品一区二区三区免费| 肥臀熟女一区二区三区| 国产高清一区二区三区四区| 亚洲av无码片vr一区二区三区 | 国产日韩一区二区三免费高清| 无码欧精品亚洲日韩一区夜夜嗨| 在线精品自拍亚洲第一区| 亚洲av日韩综合一区久热| 综合一区自拍亚洲综合图区| 欧美人妻一区黄a片| 无码一区二区三区中文字幕| 成人免费观看一区二区| 亚洲国产精品无码第一区二区三区| 精品人妻中文av一区二区三区| 无码人妻精品一区二区三区66 | 国产日韩一区二区三区在线播放| 亚洲欧洲精品一区二区三区| 亚洲综合一区无码精品| 韩国精品福利一区二区三区| 国产精品一区二区电影| 亚洲国产高清在线一区二区三区| 国产av天堂一区二区三区 | 一区二区三区四区无限乱码| 久久亚洲中文字幕精品一区| 国产在线不卡一区二区三区| 亚洲国产美女福利直播秀一区二区|