GO語言面試系列:(五)Gopher 全棧面試參考

先前準備 Golang 面試用的筆記混移,僅供參考廓译。

前言

本文結(jié)構(gòu):

1.  └──計算機基礎(chǔ)
2.       ├── 計算機網(wǎng)絡
3.       ├── 數(shù)據(jù)結(jié)構(gòu)
4.       ├── 算法
5.       ├── 操作系統(tǒng)
6.       ├── 數(shù)據(jù)庫
7.       └── OOP 與設計模式
8.  └── Golang 面試題

參考資料:筆試面試知識整理Golang 面試題解析乙濒、Go面試題答案與解析

這篇文章的內(nèi)容力大多一筆帶過陕赃,細節(jié)上我參考的書籍有:

計算機網(wǎng)絡

  • TCP / UDP 傳輸層:端到端的服務
  • IP 網(wǎng)絡層:點到點的服務

HTTP 協(xié)議

請求報文

1.  <method> <request-URL> <version>    # 狀態(tài)行       # 狀態(tài)行
2.  <headers>                           # 請求頭       # 響應頭
3.  <entity-body>                       # 請求實體     # 響應體

HTTP 協(xié)議不限制 GET URL 長度,但瀏覽器限制字符數(shù)(Chrome 8K)& 也不限制 POST 資源大小

  • GET:查
    • 安全的:獲取信息甘有,非修改信息诉儒。一般不會產(chǎn)生副作用
    • 冪等的:同一 URL 多個請求返回同一結(jié)果
  • POST:改,服務端通過請求 header 的 Content-Type 字段解析實體數(shù)據(jù)亏掀。提交數(shù)據(jù)的方式:
    • application/x-www-form-urlencoded:瀏覽器原生的 form 表單忱反,提交的數(shù)據(jù)按 url 編碼,Ajax大多默認使用
    • form_data:表單文件上傳
    • application/json:API 使用較多

響應報文

狀態(tài)行:協(xié)議版本滤愕、狀態(tài)碼缭受、狀態(tài)描述

1: Informational

  • 100 continue:POST 提交數(shù)據(jù)大于 100KB 時候發(fā)的第一個請求,允許上傳則返回 100

2:Success

  • 200 OK:請求被成功處理该互,GET 返回資源米者、POST 返回對請求處理的結(jié)果
  • 204 No Content:請求處理完畢,但不返回響應體宇智,客戶端頁面不刷新

3:Redirection

  • 301 Moved Permanently:永久重定向蔓搞,資源分配了新的 URI,處理:
    • HEAD:響應頭的 Location 指明新的 URI
    • GET:Location 指明新 URI & 在響應體中附上 URI
  • 302 Moved Temporarily:臨時性重定向随橘,希望用戶本次能訪問新的 URI喂分。重定向后的請求方法不變
  • 303 See Other:請求資源有另一個 URI,重定向后的方法變?yōu)?GET 獲取新 URI注意: 很多瀏覽器將 303 理解為 302机蔗,直接使用 GET 請求 Location 中的 URI
  • 304 Not Modified:請求頭中帶有 If-Modified蒲祈、If-Match,自從上次請求后資源并未更新萝嘁,則不發(fā)送響應體梆掸。

4:Client Error

  • 400 Bad Request:請求報文有語法錯誤
  • 401 Unauthorized:請求需要有 HTTP 認證(nginx 的 auth_basic),返回 401 時頭部中www-authenticate 指明認證方式牙言,再次請求時也需帶上 authorization 認證信息
  • 403 Forbidden:訪問被拒絕酸钦,響應實體中可說明原因
  • 404 Not Found:請求資源不存在、403 不想說明原因

5:Server Error

  • 500 Internel Error:服務器處理請求出錯
  • 502 Bad Gateway: 服務器作為代理咱枉,從 upstream 收到無效響應
  • 503 Server Unavailable:服務器暫時無法處理請求卑硫,恢復時間在 Retry-After

Conditional Get (條件 GET)

用戶訪問過該網(wǎng)頁徒恋,再次訪問。

GET 頭部帶有 If-Modified-Since:欢伏,若響應 304入挣,則直接使用瀏覽器的緩存。否則返回正常實體

持久連接

HTTP 1.0 中:客戶端請求頭添加 Connection: Keep-alive硝拧,服務端同樣在響應頭中添加径筏,保持連接

HTTP 1.1 中:默認所有連接都是長連接,添加 Connection: Close 才關(guān)閉河爹,設置

  • Keep-Alive: timeout=5, max=100:長連接保持 5s匠璧,最多接收 100 次請求后斷開
  • 注意:Keep-Alive 連接也是無狀態(tài)的
  • 傳輸結(jié)束的條件:傳輸?shù)臄?shù)據(jù)達到 Content-Length

HTTP Pipelining 管線化

批量提交 HTTP 請求,不排隊等待響應才發(fā)送下一個請求:請求1 -> 響應1 -> 請求2 -> 響應2 -> 請求3 -> 響應3 變?yōu)?請求1 -> 請求2 -> 請求3 -> 響應1 -> 響應2 -> 響應3

  • 管線化機制僅 HTTP1.1 支持
  • 只支持 GET咸这、POST

HTTP1.0 中發(fā)下一個請求前夷恍,必須等待響應。

會話追蹤

HTTP 請求是無狀態(tài)的協(xié)議媳维,不會保存客戶端信息酿雪,實現(xiàn):

cookie

  • 服務端發(fā)送給客戶端的一小段信息,客戶端每次請求都會帶上侄刽,在有效期內(nèi)識別身份指黎。
  • 分為保存在瀏覽器的臨時 cookie 和保存在內(nèi)存的永久 cookie
  • 可被禁用

session

  • 服務端創(chuàng)建 session 對象并用 sessionID 標識,將 sessionID 放到 cookie 中州丹,發(fā)送給客戶端
  • cookie 被禁用醋安,session 也會生效

token(重寫 URL)

  • 在 URL 中添加標識每個用戶的 token(cookie 被禁用時,將 sessionID 重寫到 URL 中)

HTTP 安全

CSRF 跨站請求偽造:攻擊者知道所有參數(shù)墓毒、構(gòu)造合法請求

偽造成其他用戶吓揪,發(fā)起請求:如拼接惡意鏈接給其他用戶點擊。防范:

  • 關(guān)鍵操作限制 POST
  • 合適的使用驗證碼
  • 添加 token:發(fā)起請求時添加附加的 token 參數(shù)所计,值隨機柠辞。服務端做驗證
  • header refer:外部來源可拒絕請求
XSS 跨站腳本攻擊:在客戶端不知情的情況下運行 JS 腳本。防范:
  • 過濾和轉(zhuǎn)義用戶的輸入內(nèi)容:htmlspecialchars()
  • 限制參數(shù)類型
  • 文件上傳做大小主胧、類型限制

TCP 協(xié)議

特點

  • 面向連接叭首、可靠、字節(jié)流服務:有 TCP 緩沖踪栋,可切割較長數(shù)據(jù)塊焙格、累積較短數(shù)據(jù)塊。與 UDP 每次數(shù)據(jù)報不同
  • 校驗和己英、確認和重傳機制來保證可靠傳輸
  • 動態(tài)改變滑動窗口來控制流量
  • 一對一的通信间螟,不能用于多播個廣播

應用:HTTP、FTP损肛、SMTP厢破、SSH(數(shù)據(jù)準確性要求高)

優(yōu)點:穩(wěn)定可靠

缺點:慢、效率低治拿、占資源多摩泪、易攻擊(DDOS)

三次握手 Three-way Handshake

客戶端執(zhí)行 connect() 主動連接:

1.  A:聽得到嗎?
2.  B:聽得到劫谅,你能聽到我嗎见坑?
3.  A:可以,我們可以交流了233
4.
5.  前兩次:保證 B 能接收到 A 的信息捏检,并作出正確響應
6.  第三次:為了防止 A 的延遲的連接請求荞驴,B 一直在等待 A 的數(shù)據(jù)而浪費資源

理解:傳輸?shù)男诺啦皇墙^對可靠的。為了不可靠的信道上可靠的傳輸信息贯城,最少要進行三次通信熊楼。

TCP Flags 標志位:

1. SYN:synchronous 建立連接
2. ACK:acknowledgement 確認連接
3. PSH:push 推送
4. FIN:finish 釋放連接(請求方數(shù)據(jù)已發(fā)送完畢)
5. RST: reset 重置(復位請求)
6. URG: urgent 緊急

1.SYN = 1 & ACK = 0:請求連接報文
2.SYN = 1 & ACK = 1:同意建立連接的響應報文

過程:

  • 第一次握手:客戶端請求建立連接SYN = 1,Seq = x能犯,進入 SYN_SEND 狀態(tài)鲫骗,等待服務端應答
  • 第二次握手:服務器允許建立連接SYN = 1,ACK = x+1踩晶,Seq = y执泰,進入 SYNC_RCVD 狀態(tài),等待客戶端確認
  • 第三次握手:客戶端確認建立連接ACK = y + 1渡蜻,連接建立术吝。雙方進入 ESTABLIASHED 狀態(tài)

四次揮手 Four-way handshake

服務端和客戶端均可主動斷開連接:服務端、客戶端均需確認對方無數(shù)據(jù)再發(fā)送

  • 第一次握手:無數(shù)據(jù)再發(fā)送茸苇,主動關(guān)閉連接發(fā)送 FIN 報文排苍,等待對法發(fā)送 ACK 報文,進入 FIN_WAIT_1 狀態(tài)
  • 第二次握手:同意關(guān)閉連接發(fā)送 ACK 報文確認可關(guān)閉税弃,并將未發(fā)送完畢的數(shù)據(jù)推送給對方
  • 第三次握手:請求對方關(guān)閉連接發(fā)送 FIN 報文纪岁,等待 ACK 報文
  • 第四次握手:關(guān)閉發(fā)送 ACK,進入 TIME_WAIT 狀態(tài)则果,過 2 MSL(最大分段生存時間)未收到重傳信息幔翰,直接關(guān)閉。

注意: 中間直接發(fā)送 ACK + FIN西壮,則主動方會直接跳過 FIN_WAIT_2 狀態(tài)

TCP Keep-Alive 機制(心跳包)

數(shù)據(jù)交互完畢后遗增,一方主動釋放連接。但出現(xiàn)意外時款青,TCP 連接不能及時釋放做修,導致要維護很多半打開的連接。

實現(xiàn):定時(半秒等)給對方發(fā)一個探測包,若收到 ACK 則認為連接存活饰及,若 重試一定次數(shù) 都沒收到回應則直接丟棄該 TCP 連接蔗坯。

在我的 B 站直播間數(shù)據(jù)爬蟲 抓取時,就需要每隔半分鐘給 B 站的彈幕服務器發(fā)一個心跳包燎含,否則連接會在一分鐘后斷開宾濒。

UDP 協(xié)議

特點

  • 不可靠:沒有確認、超時重傳屏箍、序列號機制:UDP 數(shù)據(jù)報不保證能送達绘梦、不保證數(shù)據(jù)報的順序
  • 無需建立連接:創(chuàng)建 UDP 連接前無需握手創(chuàng)建連接
  • 一次發(fā)送一個報文,給定報文長度:過長 IP 層會分片
  • 支持多播和廣播

應用:DNS赴魁、流媒體(速度要求 > 質(zhì)量要求)

優(yōu)點:快卸奉、比 TCP 稍安全

缺點:不可靠、不穩(wěn)定

TCP UDP
報文 面向字節(jié)流 面向報文
雙工性 全雙工 一對一颖御、一對多榄棵、多對一、多對多
流量控制 滑動窗口
擁塞控制 快重傳郎嫁、快恢復
傳輸速度

IP 協(xié)議

地址分類

IPv4 用點分十進制表示秉继,IP 地址 = 網(wǎng)絡地址 + 主機地址(層次)

全零 0.0.0.0 :本主機、全一:255.255.255.255 當前子網(wǎng)的廣播地址

A 類:8 – 1(0) = 7 位網(wǎng)絡號

  • 主機A的地址為:58.1.2.3/8,前面58位于1~127之間,所以這是一個A類地址.
  • 跟主機A位于同一個網(wǎng)絡中的IP地址有 : 58.0.0.1 ~ 58.255.255.254,一共有 2^24-2個
  • 不包括:58.0.0.0(網(wǎng)絡地址)跟58.255.255.255(廣播地址)

B 類:16 – 2(10) = 14 位網(wǎng)絡號

C 類:24 – 3(110) = 21 位網(wǎng)絡號

子網(wǎng)掩碼

用子網(wǎng)掩碼劃分一個 IP 的網(wǎng)絡地址和主機地址泽铛。

IP & 子網(wǎng)掩碼 = 網(wǎng)絡地址

192.168.1.1/24192.168.1.1/255.255.255.0 的簡寫尚辑,前 24 位為網(wǎng)絡號

子網(wǎng)劃分:將大的整體網(wǎng)絡劃為小的子網(wǎng)絡

Socket 編程

socket:三元組(IP 地址、協(xié)議盔腔、端口號)標識網(wǎng)絡中唯一的進程杠茬,在 unix 中是文件

socket 使用了門面 Facade 模式:外部與內(nèi)部的通信必須經(jīng)過 facade

socket 隱藏了 TCP/IP 細節(jié),開放交互接口弛随。有:

1. socket() // 創(chuàng)建套接字
2. bind()   // 將套接字綁定到服務器地址上
3. listen() // 等待連接請求
4. accept() // 允許連接
5. read()   // 讀數(shù)據(jù)
6. write()  // 寫數(shù)據(jù)
7. close()  // 關(guān)閉連接

搭建簡單的 Server:

  • 等待連接
  • 建立連接
  • 接收請求:讀取 HTTP 請求報文
  • 處理請求:訪問資源(文件)
  • 構(gòu)建響應:創(chuàng)建 HTTP 響應報文
  • 發(fā)送響應

數(shù)據(jù)結(jié)構(gòu)

1.└── 數(shù)據(jù)結(jié)構(gòu)
2.   ├── 數(shù)組
3.   ├── 鏈表
4.   ├── 棧
5.   ├── 隊列
6.   ├── 哈希表
7.   ├── 二叉樹
8.   ├── 堆
9.   └── 字典樹 trie

參考資料:常見數(shù)據(jù)結(jié)構(gòu)及其多種實現(xiàn)的可視化

數(shù)組 Array

元素在內(nèi)存中連續(xù)存放瓢喉。每個元素占用內(nèi)存相同,可通過下標算出元素位置快速訪問

優(yōu)點:訪問快 O(1)

缺點:增加舀透、刪除元素需要移動大量元素栓票,慢 O(N)

場景:快速訪問元素,很少插入和刪除元素

數(shù)組 鏈表
內(nèi)存分配愕够、元素存儲位置 靜態(tài)分配內(nèi)存(棧走贪,系統(tǒng)自動分配) 動態(tài)分配內(nèi)存(堆,申請和管理麻煩)
分配方式 系統(tǒng)自動分配惑芭、速度快 自己申請和管理坠狡、new 慢
大小 編譯時確定语御,具體值 是不連續(xù)的內(nèi)存區(qū)域

鏈表 Linked List

元素在內(nèi)存中不是連續(xù)存放贪婉。元素間通過指向指針聯(lián)系在一起,訪問元素必須從第一個元素開始遍歷查找

優(yōu)點:插入济炎、刪除元素只需改變指針,快 O(1)

缺點:訪問慢 O(N)

場景:經(jīng)常插入凯亮、刪除元素

分類

  • 單向鏈表:節(jié)點僅指向下一節(jié)點边臼,最后一個節(jié)點指向 nil
  • 雙向鏈表:每個節(jié)點有 2 個指針 prenext,最后一個節(jié)點的 next 指向 nil
  • 循環(huán)鏈表:單鏈表 + 最后一個節(jié)點指向第一個節(jié)點

時間復雜度

  • 查找:O(N)
  • 插入触幼、移除:O(1)

棧 Stack

元素遵循后進先出(LIFO)原則硼瓣。元素僅在表尾(棧頂)進行插入(入棧 push)究飞、刪除(出棧 pop

實現(xiàn)

  • 單鏈表實現(xiàn):保存頭節(jié)點的指針置谦,在頭節(jié)點前入棧、頭節(jié)點上出棧
  • 數(shù)組實現(xiàn):直接操作數(shù)組最后一個元素亿傅,可能出現(xiàn)數(shù)組溢出:
    • 空棧(空數(shù)組)上 pop()
    • 滿棧(滿數(shù)組)上 push()媒峡,加倍數(shù)組大小

時間復雜度

  • 查找:O(N)
  • 插入、刪除:O(1)

隊列

元素遵循先進先出(FIFO)原則葵擎。元素在一端插入(進隊列 enqueue)谅阿、另一端刪除(出隊列 dequeue)

出隊列元素是在隊列中存在時間最長的元素。

實現(xiàn)

  • 單鏈表實現(xiàn):保存指向首尾節(jié)點的指針酬滤,從鏈表尾進隊列签餐,鏈表頭出隊列
  • 數(shù)組實現(xiàn):修改 arr[0] 進隊列,修改 arr[len - 1] 出隊列

時間復雜度

  • 查找:O(N)
  • 插入盯串、刪除:O(1)

哈希表

散列表:根據(jù) key 鍵值直接訪問數(shù)據(jù)的內(nèi)存地址

hash(data) = key:hash() 是一類算法氯檐,處理任意長度的 data,得到定長的 key 值体捏,過程不可逆冠摄。

若 data 是數(shù)據(jù)集,則 key 也是數(shù)據(jù)集几缭,將 keys 與原始數(shù)據(jù)一一映射就得到哈希表河泳,即 M[key] = data

二叉樹

  • 滿二叉樹:深度為 k 且有 2^k -1 個節(jié)點的二叉樹
  • 完全二叉樹:最后一層只缺右邊節(jié)點,其它層節(jié)點數(shù)已為最大值

遍歷方式(棧實現(xiàn)較好)

  • 前序遍歷:根 -> 左 -> 右:abdefgc
  • 中序遍歷:左 -> 根 -> 右:debgfac
  • 后序遍歷:左 -> 右 ->根:edgfbac

二叉搜索樹

性質(zhì):左子節(jié)點均小于根節(jié)點年栓、右子節(jié)點均大于根節(jié)點

復雜度

  • 搜索:O(log(n))
  • 插入和刪除:O(log(n))

算法

└── 算法
     ├── 排序
     ├── 查找
     └── 字符串算法

參考資料:常見算法的過程可視化拆挥、常見算法的 Go 實現(xiàn)

排序

數(shù)據(jù)大小 n,好的復雜度 O(logN)某抓,壞的 O(N2)

應用場景

  • n 較兄酵谩:直接插入排序
  • 基本有序:冒泡排序、直接插入
  • n 較大:快速排序搪缨、歸并排序食拜、堆排序等 O(NlogN)

交換排序一:冒泡排序

過程

  • 比較相鄰元素,前大于后就交換副编。
  • 遍歷操作第 1~N 個元素负甸,此時 第 N 個元素最大。
  • 遍歷操作 1~N-1,重復遍歷并比較呻待、交換打月。…
  • 嵌套遍歷結(jié)束即完成排序蚕捉。

優(yōu)化

  • 設置 flag奏篙,發(fā)生交換設為 true,某趟提前排序完畢則為 false迫淹,直接退出秘通。
  • 記錄每輪最后發(fā)生排序的位置,下輪遍歷到此處即可敛熬。

分析

情況 復雜度
最佳情況:已有序肺稀,全遍歷 1 次 O(N)
最壞情況:反序,全遍歷 N 次 O(N^2)
平均情況 O(N^2)

?

交換排序二:快速排序

過程

  • 選取基準:從數(shù)組中選一個數(shù)(第一個)作為基準
  • 分區(qū):遍歷數(shù)組应民,比基準更小的值放在基準前邊话原、更大的在后邊
  • 遞歸:遞歸的在分區(qū)后的數(shù)組中,再選基準诲锹、分區(qū)

分析

情況 復雜度
最佳 O(logN)
最壞(數(shù)組反序繁仁、數(shù)組元素全部相同) O(N^2)
平均 O(logN)

?

選擇排序一:簡單選擇排序

過程

  • 遍歷第 1 次:找出最小的元素置于第 1 位
  • 遍歷第 N-1 次:排序完畢

分析

情況 復雜度
最佳、最差归园、平均 O(N^2)

選擇排序二:堆排序

過程

  • 將無序的數(shù)組構(gòu)建成二叉樹
  • 二叉樹整理為堆(完全二叉樹)
  • 輸出根結(jié)點黄虱,再次整理堆輸出根結(jié)點

分析

情況 復雜度
最佳、最差蔓倍、平均 O(logN)

插入排序一:直接插入排序

過程

  • 第一個元素(認為已排序好)
  • 從第二個元素開始悬钳,往后選擇元素向前遍歷,找到合適的位置插入
  • 遍歷到最后一個位置偶翅,排序完畢

分析

情況 復雜度
最佳(數(shù)組升序) O(N)
最壞(數(shù)組反序) O(N^2)
平均 O(N^2)

插入排序二:希爾排序

過程:選擇一個固定(動態(tài))的步長默勾,對步長內(nèi)的元素進行直接插入排序

分析

情況 復雜度
最佳、最壞聚谁、平均(都要步長分割母剥、遍歷) O(NlogN)

歸并排序

過程

  • 將長度為 N 的序數(shù)組分為 N / 2 的子數(shù)組
  • 遞歸劃分子數(shù)組,子數(shù)組內(nèi)部排序

分析

情況 復雜度
最佳 O(N)
最壞 O(NlogN)
平均 O(NlogN)

基數(shù)排序(非比較)

過程

  • 獲取數(shù)組中最大值的位數(shù) b
  • 從 1 ~ b 遍歷組合位數(shù)相同的元素

分析

情況 復雜度
最佳形导、最壞环疼、平均 O(N * b)

查找

無序查找:順序查找

  • 順序掃描序列,依次比較值
  • 復雜度:O(N)

有序查找(無序序列需要提前排序)

二分查找(折半查找)

  • 找到中間節(jié)點比較值朵耕,相等則查找到炫隶,更小則繼續(xù)對左邊折半查找,更大則向右邊
  • 查找比對點:mid = (low + high) / 2mid = low + (high - low) / 2
  • 復雜度:比較次數(shù)阎曹,O(log2 N)

插值查找

  • 動態(tài)的改進二分查找的查找點伪阶,使其更接近區(qū)間
  • 查找對比點:mid = low + (key - arr[low]) / (arr[high] - arr[low]) * (high - low)
  • 復雜度:O(log2(log2N))

二叉查找樹

  • 中序遍歷獲得排序好的數(shù)組
  • 復雜度:一般 O(log2N)煞檩,最壞情況 單支樹 O(N)

平衡二叉查找樹(AVL 樹)

  • 任何節(jié)點的 2 棵子樹,高度差最多為 1
  • 平衡:根結(jié)點到任意一個葉子節(jié)點栅贴,距離都相等

操作系統(tǒng)

體系結(jié)構(gòu)

  • 機器碼:最高位 0 為正斟湃、1 為 負
  • 原碼:符號位 + 真值絕對值的二進制
  • 反碼:正數(shù)反碼就是本身、負數(shù)除符號位外取反
  • 補碼:正數(shù)補碼就是本身檐薯、負數(shù)除符號位外取反 + 1
1.   [+1] = [00000001]原 = [00000001]反 = [00000001]補
2.   [-1] = [10000001]原 = [11111110]反 = [11111111]補
  • 1 byte = 8 bits凝赛,1 word = 2 byte(16位)= 4 byte(32位機)& 字是計算機數(shù)據(jù)處理和運算的單位
  • 字節(jié)序:占用內(nèi)存超過 1 byte 的數(shù)據(jù)在內(nèi)存中的存放順序
    • 小端字節(jié)序:低字節(jié)數(shù)據(jù)放在內(nèi)存低地址
    • 大端字節(jié)序:低字節(jié)數(shù)據(jù)放在內(nèi)存高地址(符合閱讀習慣,網(wǎng)絡中數(shù)據(jù)傳輸?shù)膮f(xié)議坛缕,即網(wǎng)絡字節(jié)序)
      B 站直播數(shù)據(jù)抓取 中墓猎,請求數(shù)據(jù)的打包格式就是大端字節(jié)序,否則連接到彈幕服務器祷膳。
0x12345678 的存儲:

Big Endian
低地址                                            高地址
---------------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     12     |      34    |     56      |     78    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Little Endian
低地址                                            高地址
---------------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     78     |      56    |     34      |     12    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

基礎(chǔ)

操作系統(tǒng)功能:文件管理陶衅、存儲管理、輸入輸出管理直晨、作業(yè)管理、進程管理

中斷

  • CPU 暫停執(zhí)行當前程序膨俐,去執(zhí)行中斷程序
  • 中斷的優(yōu)先級指明處理的緊急程度勇皇,如:機器錯誤 > 時鐘 > 磁盤 > 網(wǎng)絡設備 > 終端 > 軟件中斷

系統(tǒng)調(diào)用

  • 2 個級別:核心態(tài)、用戶態(tài)
  • 程序執(zhí)行一般在 user model焚刺,需要使用操作系統(tǒng)服務(創(chuàng)建敛摘、讀寫文件),請求切換到 kernel model 執(zhí)行
  • 核心態(tài)能存取用戶乳愉、內(nèi)核的指令和數(shù)據(jù)兄淫,用戶態(tài)只能存取用戶自己的指令和數(shù)據(jù)

中斷和系統(tǒng)調(diào)用的關(guān)系:程序申請核心態(tài)時,將產(chǎn)生一個軟件中斷蔓姚,系統(tǒng)將處理

并發(fā)多任務

多道程序:程序運行捕虽, CPU 空閑時(等待 IO),此時 CPU 去運行其他程序

分時系統(tǒng):改進后的多道程序坡脐,程序運行一段時間后會主動讓出 CPU

多任務系統(tǒng):操作系統(tǒng)從底層接管所有硬件資源泄私,程序以進程運行,程序運行超時會被強制暫停

進程

運行中的程序

4 個地址空間

  • 文本域:要執(zhí)行的代碼
  • 數(shù)據(jù)域:存放變量备闲、程序執(zhí)行期間動態(tài)分配的內(nèi)存
  • 堆棧:存放本地變量和指令

3 種狀態(tài)

  • 等待態(tài):IO
  • 就緒態(tài):等待系統(tǒng)分配 CPU 運行
  • 運行態(tài):占用 CPU 正在處理

4 種進程間通信

  • 消息傳遞:pipe管道
  • 同步:信號量晌端、讀寫鎖
  • 內(nèi)存共享
  • 遠程過程調(diào)用:RPC

死鎖:多個進程因循環(huán)等待資源而都無法執(zhí)行

線程

輕量級進程

  • 解決問題:很多不同的進程需要共享同樣的資源(文件),切換進程的成本很高
  • 是可以獨立運行的單位恬砂,切換快速咧纠、開銷小 & 可并發(fā)執(zhí)行
  • 共享進程的資源:在同一進程中的線程因為有相應的地址空間,可以共享進程已打開的文件泻骤、定時器等

協(xié)程

  • 微線程漆羔,coroutine:用戶級的線程
  • 線程是搶占式調(diào)度乳幸、協(xié)程是協(xié)同式調(diào)度,避免無意義的搶占钧椰,但是調(diào)度由用戶決定

IO 多路復用

內(nèi)核發(fā)現(xiàn)某個進程指定的 IO 準備讀取粹断,就會通知該進程,如客戶端處理多個描述符時嫡霞,大大減小創(chuàng)建和維護的開銷瓶埋。

并發(fā)與并行

  • 并發(fā):多個操作可在重疊的時間運行
  • 并行:同一時刻有多條指令在執(zhí)行,多核是并行的前提诊沪。

數(shù)據(jù)庫

事務:一系列 SQL 集合

ACID 特性

  • 原子性 automatic:事務是原子工作單位养筒,要么全部執(zhí)行、要么全部不執(zhí)行
  • 一致性 consistency:數(shù)據(jù)庫通過事務完成狀態(tài)轉(zhuǎn)變
  • 隔離性 isolation:事務提交前端姚,對數(shù)據(jù)的影響是不可見的
  • 持久性 duration:事務完成后晕粪,對數(shù)據(jù)的影響是持久的

4 種隔離級別

  • 臟讀:一個事務讀取了另一個事務尚未提交的修改
  • 非重復讀:一個事務對同一行數(shù)據(jù)讀取兩次,得到不同結(jié)果
  • 幻讀:事務在操作過程中進行了兩次查詢渐裸,第二次的結(jié)果包含了第一次未出現(xiàn)的新數(shù)據(jù)
  • 丟失修改:當兩個事務更新相同的數(shù)據(jù)源巫湘,第一個事務提交,第二個撤銷昏鹃。那么第一個也要撤銷

3 種實現(xiàn)隔離的鎖

  • 共享鎖 S 鎖:只讀 SELECT 操作尚氛,鎖定共享資源,阻止其他用戶寫數(shù)據(jù)
  • 更新鎖 U 鎖:阻止其他用戶更新數(shù)據(jù)
  • 獨占鎖 X 鎖:一次只能有一個獨占鎖占用一個資源洞渤,阻止添加其他所有鎖阅嘶。有效防止臟讀

索引

優(yōu)點

  • 大大加快檢索速度
  • 加快表之間的關(guān)聯(lián)
  • 唯一性索引 UNIQUE:保證行數(shù)據(jù)的唯一性

缺點

  • 創(chuàng)建和維護消耗時間和物理空間

場景

  • 用在經(jīng)常需要連接的字段:如外鍵,加快連接速度
  • 用在經(jīng)常需要排序的字段:索引已排序载迄,直接利用讯柔,加快排序時間

OOP

三個基本特征:封裝、繼承护昧、多態(tài)

封裝

  • 提取對象的特征魂迄,抽象成類。
  • 外部只能訪問 public 的屬性和方法捏卓。private 的屬性和方法內(nèi)部調(diào)用极祸,設置 getter、setter 開放接口允許外部訪問和修改私有數(shù)據(jù)怠晴,protected 的數(shù)據(jù)和方法子類繼承和調(diào)用

繼承:使用現(xiàn)有類的所有功能遥金。

多態(tài):子類覆蓋父類的同名方法

??

Golang 面試題

問答類

1. 在 Go 中如何使用多行字符串?

使用反引號 “ 來包含多行字串蒜田,或使用 + 來連接多行字符串(注意換行會包含\n稿械,縮進會包含 \t,空格沒有轉(zhuǎn)義符):

1.func main() {
2.   str1 := `
3. line1
4.    line2
5.`
6.    str2 := "\n line1\n\t" +
7.      "line2\n"
8.    fmt.Println(str1 == str2) // true
9.}

2. 如何獲取命令行的參數(shù)冲粤?

有兩種方法:

使用 os 庫美莫,如:

1.  func main() {
2.     args := os.Args
3.     if args == nil  { // 校驗參數(shù)并輸出提示信息
4.        return
5.    }
6.    fmt.Printf("%T\n", args)
7.    fmt.Printf("%v\n", args)
8. }

可以看出 os.Args 接收到的參數(shù)是 string slice页眯,元素分別是運行的程序名、多個參數(shù)值:

使用 flag 庫厢呵,步驟:

  • 定義各個參數(shù)的類型窝撵、名字、默認值與提示信息
  • 解析
  • 獲取參數(shù)值
func main() {
    name := flag.String("name", "", "Your name")
    var age int
    flag.IntVar(&age, "age", -1, "Your age")

    flag.Parse()

    println("name", *name)
    println("age", age)
}

注意上邊獲取參數(shù)值的兩種方式襟铭,使用時也有所不同:

func Int(name string, value string, usage string) *string // 返回地址
func IntVar(p *int, name string, value int, usage string) // 修改第一個參數(shù)值

3. 如何在不輸出的情況下格式化字符串碌奉?

使用 func Sprintf(format string, a ...interface{}) string 即可,常用在手動組合 SQL 語句上:

func main() {
    fmt.Println(formatSQL(20))
}

func formatSQL(id int) string {
    return fmt.Sprintf("SELECT * FROM users WHERE id=%d", id)
}

4. 如何交換兩個變量的值寒砖?

直接使用元組(tuple)賦值即可:

a, b = b, a

注意元組賦值是對應有序賦值的:

1. a, b, c = b, c, a // 交換三個變量的值
2.
3. a := 1
4. b := 2
5. a, b, a = b, a, b // a = 2, b = 1

5. 如何復制 slice赐劣、map 和 interface 的值?

slice:

func main() {
    names := []string{"Tom", "Jerry"}
    nums := []string{"one", "two", "three"}
    pNames := names   // 確認 names 被更新 

    // names = nums   // 直接賦值
      
    // fmt.Println(copy(names, nums))   // 使用 copy
    fmt.Println(names, nums, pNames)
}
  • 直接賦值, 底層數(shù)組將不會更新:

  • 使用 copy()
    返回值是 min(len(names), len(src))哩都,只會拷貝前兩個元素魁兼,pNames 的值顯示 names 的底層數(shù)組已被覆蓋更新:

map:

最簡單的方法,遍歷所有 key:

func main() {
    src := map[string]bool{"key1": false, "key2": true}
    dst := make(map[string]bool)

    for key, value := range src { // 遍歷所有 key
        dst[key] = value
    }
    fmt.Println(dst)
}

interface:

Go 中沒有內(nèi)建的函數(shù)來直接拷貝 interface 的值漠嵌,也不能直接賦值咐汞。如 2 個 struct 的字段完全一致,可以使用強制類型轉(zhuǎn)換或反射來賦值献雅。

參考:關(guān)于結(jié)構(gòu)體復制問題碉考、Copying Interface Values In Go

6. 下邊兩種 slice 的聲明有何不同?哪種更好挺身?

var nums []int
nums := []int{}

第一種如果不使用 nums,就不會為其分配內(nèi)存锌仅,更好(不使用編譯也不會通過)章钾。

寫出程序運行輸出的內(nèi)容

1. 考察多個 defer 與 panic 的執(zhí)行順序

func main() {
    deferCall()
}

func deferCall() {
    defer func() { fmt.Println("打印前") }()
    defer func() { fmt.Println("打印中") }()
    defer func() { fmt.Println("打印后") }()

    panic("觸發(fā)異常")
}

defer 可以類比為析構(gòu)函數(shù),多個 defer 本身的執(zhí)行是棧 LIFO 先進后出的順序热芹,代碼拋出的 panic 如果在所有 defer 中都不使用 recover 恢復贱傀,則直接退出程序。

如果手動使用 os.Exit() 退出伊脓,則 defer 不執(zhí)行府寒。

2. 考察 defer 與 return 的執(zhí)行順序

func main() {
    fmt.Println(double1(5))
    fmt.Println(double1(6))
    fmt.Println()
    fmt.Println(double2(5))
    fmt.Println(double2(6))
}

// 匿名返回
// 加倍參數(shù),若結(jié)果超過 10 則還原
func double1(v1 int) int {
    var v2 int
    defer func() {
        if v2 > 10 {
            v2 = v1 // v2 不會被修改
        }
    }()

    v2 = v1 * 2
    return v2 
}

// 有名返回
func double2(v1 int)(v2 int) {
    // v2 與函數(shù)一起被聲明报腔,在 defer 中能被修改
    defer func() {
        if v2 > 10 {
          v2 = v1 // v2 被修改
        } 
    }() 

    v2 = v1 * 2
    return
}

注意 return var 會分為三步執(zhí)行:

return 語句為 var 賦值

  • 匿名返回值函數(shù):先聲明株搔,再賦值
  • 有名返回值函數(shù):直接賦值

檢查是否存在 defer 語句:逆序執(zhí)行多條 defer,有名返回函數(shù)可能會再次修改 var

真正返回 var 到調(diào)用處

3. 考察 goroutine 的傳值方式

func main() {
    runtime.GOMAXPROCS(1) // 強制使多個 goroutine 串行執(zhí)行
    wg := sync.WaitGroup{}
    wg.Add(10)

    for i := 0; i < 5; i++ {
        go func() {
            fmt.Println("i: ", i)
            wg.Done()
        }()
        // time.Sleep(1 * time.Second)  // 此時將順序輸出 1 2 3 4 5 
    }

  for i := 0; i < 5; i++ {
      go func(i int) {
          fmt.Println("i: ", i)
          wg.Done()
      }(i)
  }
  wg.Wait()
}

第一個 for 循環(huán):以極快的速度分配完 5 個 goroutine纯蛾,此時 i 的值為 5纤房,gouroutine 得到的 i 都是 5

第二個 for 循環(huán):每次都會將 i 的值拷貝一份傳給 goroutine,得到的 i 不同翻诉,輸出不同

4. 考察 defer 參數(shù)的計算時機

1. func main() {
2.     a := 1
3.     b := 2
4.     defer add("A", a, add("B", a, b))
5.     a = 0
6.     defer add("C", a, add("D", a, b))
7.     b = 1
8. }
9.
10.
11. func add(desc string, a, b int) int {
12.     sum := a + b
13.     fmt.Println(desc, a, b, sum)
14.     return sum
15. }

defer 語句會計算好 func 的參數(shù)炮姨,再放入執(zhí)行棧中捌刮。

注意第 7 行:四個 defer func 的參數(shù)此時已是確定值,不再對 defer 中的 b 造成影響舒岸。

5. 考察 Go 的組合

1. type People struct{}
2. 
3. func (p *People) ShowA() {
4.     fmt.Println("people showA")
5.     p.ShowB()
6. }
7. func (p *People) ShowB() {
8.     fmt.Println("people showB")
9. }
10.
11.
12. type Teacher struct {
13.     People
14. }
15.
16. func (t *Teacher) ShowB() {
17.    fmt.Println("teacher showB")
18. }
19.
20. func main() {
21.    t := Teacher{}
22.     t.ShowB()
23.     t.ShowA()
24. }

第 13 行: Teacher 通過嵌入 People 來獲取了 ShowA()showB()

第 16 行:Teacher 實現(xiàn)并覆蓋了 showB()

第 24 行:調(diào)用未覆蓋的 showA()绅作,因為它的 receiver 依舊是 People,相當于 People 調(diào)用

來源:https://wuyin.io/2018/03/16/golang-interviews/

添加小編微信:grey0801蛾派,歡迎交流俄认!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碍脏,隨后出現(xiàn)的幾起案子梭依,更是在濱河造成了極大的恐慌,老刑警劉巖典尾,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件役拴,死亡現(xiàn)場離奇詭異,居然都是意外死亡钾埂,警方通過查閱死者的電腦和手機河闰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來褥紫,“玉大人姜性,你說我怎么就攤上這事∷杩迹” “怎么了部念?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長氨菇。 經(jīng)常有香客問我儡炼,道長,這世上最難降的妖魔是什么查蓉? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任乌询,我火速辦了婚禮,結(jié)果婚禮上豌研,老公的妹妹穿的比我還像新娘妹田。我一直安慰自己,他們只是感情好鹃共,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布鬼佣。 她就那樣靜靜地躺著,像睡著了一般及汉。 火紅的嫁衣襯著肌膚如雪沮趣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天坷随,我揣著相機與錄音房铭,去河邊找鬼驻龟。 笑死,一個胖子當著我的面吹牛缸匪,可吹牛的內(nèi)容都是我干的翁狐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼凌蔬,長吁一口氣:“原來是場噩夢啊……” “哼露懒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起砂心,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤懈词,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辩诞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坎弯,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年译暂,在試婚紗的時候發(fā)現(xiàn)自己被綠了抠忘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡外永,死狀恐怖崎脉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伯顶,我是刑警寧澤囚灼,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站祭衩,受9級特大地震影響啦撮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汪厨,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望愉择。 院中可真熱鬧劫乱,春花似錦、人聲如沸锥涕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽层坠。三九已至殖妇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間破花,已是汗流浹背谦趣。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工疲吸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人前鹅。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓摘悴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舰绘。 傳聞我的和親對象是個殘疾皇子蹂喻,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容