㈠ golang語言面試題(golang常見面試題)
golang面試題2之判斷字元串中字元是否全都不同請實現個演算法,確定個字元串的所有字元【是否全都不同】。這我們要求【不允
許使額外的存儲結構】。給定個string,請返回個bool值,true代表所有字元全都
不同,false代表存在相同的字元。保證字元串中的字元為【ASCII字元】。字元串的
度於等於【3000】。
這有個重點,第個是ASCII字元,ASCII字元字元共有256個,其中128個是常
字元,可以在鍵盤上輸。128之後的是鍵盤上法找到的。
然後是全部不同,也就是字元串中的字元沒有重復的,再次,不準使額外的儲存結
構,且字元串於等於3000。
如果允許其他額外儲存結構,這個題很好做。如果不允許的話,可以使golang內置
的式實現。
通過strings.Count函數判斷:
使的是golang內置法strings.Count,可以來判斷在個字元串中包含
的另外個字元串的數量
還有不同的方法同樣可以實現,你了解嗎?
推薦go相關技術專欄
gRPC-go源碼剖析與實戰_帶你走進gRPC-go的源碼世界-CSDN博客
go面試題整理(附帶部分自己的解答)原文:【】
如果有解答的不對的,麻煩各位在評論寫出來~
go的調度原理是基於GMP模型,G代表一個goroutine,不限制數量;M=machine,代表一個線程,最大1萬,所有G任務還是在M上執行;P=processor代表一個處理器,每一個允許的M都會綁定一個G,默認與邏輯CPU數量相等(通過runtime.GOMAXPROCS(runtime.NumCPU())設置)。
go調用過程:
可以能,也可以不能。
因為go存在不能使用==判斷類型:map、slice,如果struct包含這些類型的欄位,則不能比較。
這兩種類型也不能作為map的key。
類似棧操作,後進先出。
因為go的return是一個非原子性操作,比如語句returni,實際上分兩步進行,即將i值存入棧中作為返回值,然後執行跳轉,而defer的執行時機正是跳轉前,所以說defer執行時還是有機會操作返回值的。
select的case的表達式必須是一個channel類型,所有case都會被求值,求值順序自上而下,從左至右。如果多個case可以完成,則會隨機執行一個case,如果有default分支,則執行default分支語句。如果連default都沒有,則select語句會一直阻塞,直到至少有一個IO操作可以進行。
break關鍵字可跳出select的執行。
goroutine管理、信息傳遞。context的意思是上下文,在線程、協程中都有這個概念,它指的是程序單元的一個運行狀態、現場、快照,包含。context在多個goroutine中是並發安全的。
應用場景:
例子參考:
waitgroup
channel
len:切片的長度,訪問時間復雜度為O(1),go的slice底層是對數組的引用。
cap:切片的容量,擴容是以這個值為標准。默認擴容是2倍,當達到1024的長度後,按1.25倍。
擴容:每次擴容slice底層都將先分配新的容量的內存空間,再將老的數組拷貝到新的內存空間,因為這個操作不是並發安全的。所以並發進行append操作,讀到內存中的老數組可能為同一個,最終導致append的數據丟失。
共享:slice的底層是對數組的引用,因此如果兩個切片引用了同一個數組片段,就會形成共享底層數組。當sliec發生內存的重新分配(如擴容)時,會對共享進行隔斷。詳細見下面例子:
make([]Type,len,cap)
map的底層是hashtable(hmap類型),對key值進行了hash,並將結果的低八位用於確定key/value存在於哪個bucket(bmap類型)。再將高八位與bucket的tophash進行依次比較,確定是否存在。出現hash沖撞時,會通過bucket的overflow指向另一個bucket,形成一個單向鏈表。每個bucket存儲8個鍵值對。
如果要實現map的順序讀取,需要使用一個slice來存儲map的key並按照順序進行排序。
利用map,如果要求並發安全,就用sync.map
要注意下set中的delete函數需要使用delete(map)來實現,但是這個並不會釋放內存,除非value也是一個子map。當進行多次delete後,可以使用make來重建map。
使用sync.Map來管理topic,用channel來做隊列。
參考:
多路歸並法:
preclass="vditor-reset"placeholder=""contenteditable="true"spellcheck="false"pdata-block="0"(1)假設有K路ahref=""數據流/a,流內部是有序的,且流間同為升序或降序;
/ppdata-block="0"(2)首先讀取每個流的第一個數,如果已經EOF,pass;
/ppdata-block="0"(3)將有效的k(k可能小於K)個數比較,選出最小的那路mink,輸出,讀取mink的下一個;
/ppdata-block="0"(4)直到所有K路都EOF。
/p/pre
假設文件又1個G,內存只有256M,無法將1個G的文件全部讀到內存進行排序。
第一步:
可以分為10段讀取,每段讀取100M的數據並排序好寫入硬碟。
假設寫入後的文件為A,B,C...10
第二步:
將A,B,C...10的第一個字元拿出來,對這10個字元進行排序,並將結果寫入硬碟,同時記錄被寫入的字元的文件指針P。
第三步:
將剛剛排序好的9個字元再加上從指針P讀取到的P+1位數據進行排序,並寫入硬碟。
重復二、三步驟。
go文件讀寫參考:
保證排序前兩個相等的數其在序列的前後位置順序和排序後它們兩個的前後位置順序相同的排序叫穩定排序。
快速排序、希爾排序、堆排序、直接選擇排序不是穩定的排序演算法。
基數排序、冒泡排序、直接插入排序、折半插入排序、歸並排序是穩定的排序演算法。
參考:
head只請求頁面的首部。多用來判斷網頁是否被修改和超鏈接的有效性。
get請求頁面信息,並返回實例的主體。
參考:
401:未授權的訪問。
403:拒絕訪問。
普通的http連接是客戶端連接上服務端,然後結束請求後,由客戶端或者服務端進行http連接的關閉。下次再發送請求的時候,客戶端再發起一個連接,傳送數據,關閉連接。這么個流程反復。但是一旦客戶端發送connection:keep-alive頭給服務端,且服務端也接受這個keep-alive的話,兩邊對上暗號,這個連接就可以復用了,一個http處理完之後,另外一個http數據直接從這個連接走了。減少新建和斷開TCP連接的消耗。這個可以在Nginx設置,
這個keepalive_timout時間值意味著:一個http產生的tcp連接在傳送完最後一個響應後,還需要hold住keepalive_timeout秒後,才開始關閉這個連接。
特別注意TCP層的keepalive和http不是一個意思。TCP的是指:tcp連接建立後,如果客戶端很長一段時間不發送消息,當連接很久沒有收到報文,tcp會主動發送一個為空的報文(偵測包)給對方,如果對方收到了並且回復了,證明對方還在。如果對方沒有報文返回,重試多次之後則確認連接丟失,斷開連接。
tcp的keepalive可通過
net.ipv4.tcp_keepalive_intvl=75//當探測沒有確認時,重新發送探測的頻度。預設是75秒。
net.ipv4.tcp_keepalive_probes=9//在認定連接失效之前,發送多少個TCP的keepalive探測包。預設值是9。這個值乘以tcp_keepalive_intvl之後決定了,一個連接發送了keepalive之後可以有多少時間沒有回應
net.ipv4.tcp_keepalive_time=7200//當keepalive起用的時候,TCP發送keepalive消息的頻度。預設是2小時。一般設置為30分鍾1800
修改:
可以
tcp是面向連接的,upd是無連接狀態的。
udp相比tcp沒有建立連接的過程,所以更快,同時也更安全,不容易被攻擊。upd沒有阻塞控制,因此出現網路阻塞不會使源主機的發送效率降低。upd支持一對多,多對多等,tcp是點對點傳輸。tcp首部開銷20位元組,udp8位元組。
udp使用場景:視頻通話、im聊天等。
time-wait表示客戶端等待服務端返回關閉信息的狀態,closed_wait表示服務端得知客戶端想要關閉連接,進入半關閉狀態並返回一段TCP報文。
time-wait作用:
解決辦法:
close_wait:
被動關閉,通常是由於客戶端忘記關閉tcp連接導致。
根據業務來啊~
重要指標是cardinality(不重復數量),這個數量/總行數如果過小(趨近於0)代表索引基本沒意義,比如sex性別這種。
另外查詢不要使用select*,根據select的條件+where條件做組合索引,盡量實現覆蓋索引,避免回表。
僵屍進程:
即子進程先於父進程退出後,子進程的PCB需要其父進程釋放,但是父進程並沒有釋放子進程的PCB,這樣的子進程就稱為僵屍進程,僵屍進程實際上是一個已經死掉的進程。
孤兒進程:
一個父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程將成為孤兒進程。孤兒進程將被init進程(進程號為1)所收養,並由init進程對它們完成狀態收集工作。
子進程死亡需要父進程來處理,那麼意味著正常的進程應該是子進程先於父進程死亡。當父進程先於子進程死亡時,子進程死亡時沒父進程處理,這個死亡的子進程就是孤兒進程。
但孤兒進程與僵屍進程不同的是,由於父進程已經死亡,系統會幫助父進程回收處理孤兒進程。所以孤兒進程實際上是不佔用資源的,因為它終究是被系統回收了。不會像僵屍進程那樣佔用ID,損害運行系統。
原文鏈接:
產生死鎖的四個必要條件:
(1)互斥條件:一個資源每次只能被一個進程使用。
(2)請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3)不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4)循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
避免方法:
埠佔用:lsof-i:埠號或者nestat
cpu、內存佔用:top
發送信號:kill-l列出所有信號,然後用kill[信號變化][進程號]來執行。如kill-9453。強制殺死453進程
gitlog:查看提交記錄
gitdiff:查看變更記錄
gitmerge:目標分支改變,而源分支保持原樣。優點:保留提交歷史,保留分支結構。但會有大量的merge記錄
gitrebase:將修改拼接到最新,復雜的記錄變得優雅,單個操作變得(revert)很簡單;缺點:
gitrevert:反做指定版本,會新生成一個版本
gitreset:重置到某個版本,中間版本全部丟失
etcd、Consul
pprof
節省空間(非葉子節點不存儲數據,相對btree的優勢),減少I/O次數(節省的空間全部存指針地址,讓樹變的矮胖),范圍查找方便(相對hash的優勢)。
explain
其他的見:
runtime2.go中關於p的定義:其中runnext指針決定了下一個要運行的g,根據英文的注釋大致意思是說:
所以當設置runtime.GOMAXPROCS(1)時,此時只有一個P,創建的g依次加入P,當最後一個即i==9時,加入的最後一個g將會繼承當前主goroutinue的剩餘時間片繼續執行,所以會先輸出9,之後再依次執行P隊列中其它的g。
方法一:
方法二:
[圖片上傳失敗...(image-4ef445-1594976286098)]
方法1:to_days,返回給的日期從0開始算的天數。
方法2:data_add。向日期添加指定時間間隔
[圖片上傳失敗...(image-b67b10-1594976286098)]
面試問題總結(一)Golang
使用go語言的好處:go語言的設計是務實的,go在針對並發上進行了優化,並且支持大規模高並發,又由於單一的碼格式,相比於其他語言更具有可讀性,在垃圾回收上比java和Python更有效,因為他是和程序同時執行的.
1.進程,線程,協程的區別,協程的優勢
2.講一下GMP模型(重點)
3.Go的GC,混合寫屏障(重點)
4.go的Slice和數組的區別,slice的擴容原理(重點)
5.講一下channel,實現原理(重點)
6.講一下Go的Map的實現原理,是否線程安全,如何實現安全(重點)
7.new和make的區別
8.說一下內存逃逸
9.函數傳指針和傳值有什麼區別
10.goroutine之間的通信方式
11.測試是怎麼做的(單元測試,壓力測試)
12.堆和棧的區別
㈡ java框架有哪些常用框架
十大常用框架:
一、SpringMVC
二、Spring
三、Mybatis
四、Dubbo
五、Maven
六、RabbitMQ
七、Log4j
八、Ehcache
九、Redis
十、Shiro