青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

戰(zhàn)魂小筑

討論群:309800774 知乎關(guān)注:http://zhihu.com/people/sunicdavy 開(kāi)源項(xiàng)目:https://github.com/davyxu

   :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  257 隨筆 :: 0 文章 :: 506 評(píng)論 :: 0 Trackbacks

2018年11月30日 #

近期在游戲demo中試驗(yàn)ECS, 深入研究Unity官方的ECS框架和第三方Entitas框架, 分享下使用ECS的心得。


Unity在2018版中加入了ECS系統(tǒng), 但處于小白鼠階段。默認(rèn)不是Unity的一部分, 需要手動(dòng)下載代碼并導(dǎo)入Packages(新特性)。官方提供海豚例子, 但除此之外例子和資料非常少。所以完全無(wú)法,也不敢在demo中貿(mào)然引入這種系統(tǒng),所以放棄官方ECS系統(tǒng)。


第三方的Entitas(https://github.com/sschmid/Entitas-CSharp)ECS框架從2015年就開(kāi)始在各地演講中介紹。整體框架基于代碼生成, 能解決一部分的代碼爆炸問(wèn)題, 而且性能也要好一些。例子,介紹非常豐富,例子雖然基于不同版本的Entitas,特性支持和最新版差不太多, 只是寫(xiě)法有細(xì)微差異, 對(duì)于理解來(lái)說(shuō)無(wú)礙。


經(jīng)過(guò)1~2天的改造, 終于將demo從傳統(tǒng)Unity寫(xiě)法改造為ECS標(biāo)準(zhǔn)寫(xiě)法,新增了46個(gè)文件, 而傳統(tǒng)邏輯一共只有16個(gè)文件,大概對(duì)比下ECS的特點(diǎn)和差異。


Entitas的ECS系統(tǒng)

1. 本來(lái)在一個(gè)對(duì)象中添加一個(gè)類(lèi)字段的過(guò)程,ECS需要添加一個(gè)類(lèi)代表Component,并且代碼生成。

這個(gè)字段一般用于描述對(duì)象的資源,處理顯示的GameObject, 表示對(duì)象的類(lèi)型等。


2. 本來(lái)一個(gè)對(duì)象的業(yè)務(wù)邏輯處理過(guò)程直接用方法解決的, ECS需要新加一個(gè)System,而操作對(duì)象需要使用Filter或Group查詢(xún)獲得。


3. 一系列的操作, 需要拆分為多個(gè)System和Component拆分處理。如果System順序不對(duì), 會(huì)造成一些詭異的bug。


4. Component不僅僅是Model承載體, 也可以是參數(shù)的數(shù)據(jù)結(jié)構(gòu)。參數(shù)Component通過(guò)Entity傳遞到System處理。 例如: 通過(guò)ECS創(chuàng)建一個(gè)方塊的過(guò)程,使用CreateTileComponent,包含創(chuàng)建Tile的位置, 創(chuàng)建Entity并添加CreateTileComponent, 在CreateTileSystem中處理就創(chuàng)建了Tile,處理完成時(shí), 需要將傳入的Entity.Destroy掉。


6. Entity上修改Component的過(guò)程, 會(huì)觸發(fā)事件。修改的過(guò)程需要使用RelaceXXX,XXX表示組件名。組件可以頻繁修改, 不用擔(dān)心添加和刪除組件過(guò)程的性能, Entitas底層處理性能只相當(dāng)于指針賦值的性能。


ECS像什么?

1. ECS中的System類(lèi)似觸發(fā)器系統(tǒng)(Event-Condition-Action),其中,Event對(duì)應(yīng)Entitas的GetTrigger+Collector,表示觸發(fā)事件。Condition對(duì)應(yīng)Filter表示在事件來(lái)源對(duì)象中找到需要的對(duì)象。 Action對(duì)應(yīng)Execute,表示實(shí)際的操作。

2. ECS中的Component類(lèi)似不用lua擴(kuò)展的Redis或者不用存儲(chǔ)過(guò)程的MySQL, 純粹純數(shù)據(jù), 而不能對(duì)數(shù)據(jù)有任何封裝操作。沒(méi)有l(wèi)ua和存儲(chǔ)過(guò)程支持的db寫(xiě)起來(lái)還是比較費(fèi)勁的,但ECS就是那么的純。


3. ECS中的Entity很尷尬,因?yàn)镃omponent是按類(lèi)別連續(xù)存儲(chǔ)的以保證性能。 邏輯又需要Entity組合成邏輯需要的復(fù)合對(duì)象。 兩邊都要照顧,所以這種設(shè)計(jì)就讓代碼量巨增,可讀性下降。



ECS企圖用一套框架滅掉設(shè)計(jì)模式

1. 單件(Singleton)在Entitas用Unique標(biāo)簽標(biāo)記Component, 在Context中就是唯一的, 其實(shí)也就是Singleton。


2. ECS干掉了傳統(tǒng)的工廠(chǎng)模式,底層統(tǒng)一對(duì)對(duì)象(Entity)和屬性(Component)統(tǒng)一管理。需要按Component中的值找回Entity時(shí), 可以使用EntityIndex。


3. Entity攜帶不同的組件時(shí),整個(gè)創(chuàng)建和銷(xiāo)毀過(guò)程被記錄并恢復(fù),其實(shí)就是Command模式


ECS適合做UI框架(類(lèi)似MVVM,MVC,MVP)么?

ECS不是專(zhuān)用的UI框架,但是可以對(duì)不同系統(tǒng)和數(shù)據(jù)間解耦。傳統(tǒng)代碼中數(shù)據(jù)修改后的Callback,ECS也可以用Listener做, 但Listener因?yàn)槟鼙4鏀?shù)據(jù), 就需要用Component保存。 所以你需要面對(duì)的是,一個(gè)Button,響應(yīng)創(chuàng)建一個(gè)參數(shù)用的Component和System,還要為數(shù)據(jù)改變寫(xiě)一套ListenComponent和Listener處理的System,酸爽吧?


Minecraft適合ECS來(lái)做么?

可以,性能應(yīng)該能提升不少,但是代碼會(huì)更繁瑣,特別像Java這種啰嗦語(yǔ)言配上ECS這種啰嗦框架,估計(jì)代碼量翻翻還是很輕松的。MC屬于特殊類(lèi)型的游戲,適合特殊領(lǐng)域特別優(yōu)化,也就是專(zhuān)門(mén)為方塊做出特別的設(shè)計(jì)來(lái)做優(yōu)化。ECS屬于通用框架,即便性能OK,但是代碼未必能有良好的可讀性。


體量小的游戲適合用ECS來(lái)做么?

可以,但不建議。特別是只有幾個(gè)人維護(hù)的工程,貿(mào)然上ECS系統(tǒng),會(huì)讓系統(tǒng)變的極為復(fù)雜。當(dāng)然你會(huì)說(shuō),如果開(kāi)發(fā)到后期,傳統(tǒng)開(kāi)發(fā)模式會(huì)導(dǎo)致代碼會(huì)亂,ECS會(huì)好些吧。掌握ECS也不是一天兩天的事情,不熟悉ECS的程序員設(shè)計(jì)出來(lái)的系統(tǒng)獲得的優(yōu)勢(shì)可能還不如用傳統(tǒng)設(shè)計(jì)方法好呢。

架構(gòu)解決的是人的問(wèn)題, 人都有問(wèn)題,用什么框架都沒(méi)辦法。


到底什么項(xiàng)目適合用ECS?

1. 大量的小個(gè)體不斷的生成和銷(xiāo)毀以及顯示,例如: 攻城戰(zhàn)中,要體現(xiàn)每個(gè)角色的移動(dòng),戰(zhàn)斗。

2. 多于5個(gè)人編寫(xiě)核心戰(zhàn)斗邏輯。互相協(xié)作和模塊切分,需要一個(gè)大家都能信服的框架,ECS可以選擇。


P.S.

不要造ECS的輪子!

很多同學(xué)看了ECS基本原理,在沒(méi)有深入使用過(guò)任何ECS系統(tǒng)時(shí)馬上操刀造輪子。ECS系統(tǒng)確實(shí)看起來(lái)簡(jiǎn)單。實(shí)際造下來(lái)你會(huì)發(fā)現(xiàn),性能非常糟糕以及不知道一些邏輯如何用ECS來(lái)解決。


總結(jié):

1. ECS確實(shí)為性能而生,沒(méi)有并發(fā)加持性能的ECS都是耍流氓,要快就要快到極致。

2. Unity中,ECS并發(fā)能擴(kuò)展CPU的利用率,但是GPU的性能依然還是DrawCall優(yōu)化那一套,別期望ECS會(huì)顛覆Unity,性能也不會(huì)快到飛起,關(guān)鍵還是要看具體的項(xiàng)目和人。

3. ECS是萬(wàn)能框架,但不全能。傳統(tǒng)架構(gòu)和設(shè)計(jì)思想也不是一無(wú)是處,熟啥用啥,怎么快怎么來(lái)!

無(wú)恥的廣告鏈接,請(qǐng)各位支持

《Go語(yǔ)言從入門(mén)到進(jìn)階實(shí)戰(zhàn)(視頻教學(xué)版)》(徐波)【摘要 書(shū)評(píng) 試讀】- 京東圖書(shū)

posted @ 2018-11-30 18:01 戰(zhàn)魂小筑 閱讀(3324) | 評(píng)論 (0)編輯 收藏

2018年8月29日 #

為了編寫(xiě)基于cellnet的新一代游戲服務(wù)器框架,最近深入研究微服務(wù),ServiceMesh等概念。研究過(guò)程中對(duì)Web和游戲兩種服務(wù)器架構(gòu)設(shè)計(jì)有一些心得,編寫(xiě)并記錄下來(lái)。(下文中,Game表示游戲服務(wù)器,Web表示W(wǎng)eb服務(wù)器) ``
狀態(tài)緩存
所謂狀態(tài)緩存,就是在內(nèi)存而非專(zhuān)業(yè)數(shù)據(jù)緩存服務(wù)器(如redis)中保存和處理邏輯數(shù)據(jù),手動(dòng)編寫(xiě)此過(guò)程較為繁瑣但是效率較高,但隨著狀態(tài)邏輯復(fù)雜性和并發(fā)、擴(kuò)容問(wèn)題提出,狀態(tài)同步會(huì)變得越來(lái)越復(fù)雜。
Game:
強(qiáng)交互性的服務(wù)器類(lèi)型需要在服務(wù)器做緩存,邏輯編寫(xiě)也較為容易,無(wú)需處理事務(wù)并發(fā)問(wèn)題。例如:組隊(duì),匹配,戰(zhàn)斗邏輯。服務(wù)器不能隨意重啟。
弱交互性的服務(wù)器類(lèi)型可配合redis做成無(wú)狀態(tài)服務(wù)器,例如:養(yǎng)成,技能升級(jí),領(lǐng)取物品等。服務(wù)器隨時(shí)支持重啟。
游戲服務(wù)器為了提高性能,早期所有服務(wù)器都是使用狀態(tài)緩存寫(xiě)法編寫(xiě),特別是MMORPG這類(lèi)強(qiáng)交互的游戲服務(wù)器尤為嚴(yán)重。
Web:
均為無(wú)狀態(tài)服務(wù)器,弱交互。使用事務(wù)方式處理并發(fā)邏輯,例如:交易,下單等。
推送,單獨(dú)發(fā)送
這里提到的所謂推送,單獨(dú)發(fā)送是與RPC區(qū)別的通訊方法。RPC要求請(qǐng)求必須有回應(yīng)。而推送單獨(dú)發(fā)送則更像是通知和廣播,無(wú)需目的方返回任何消息。
Game:
找到服務(wù)器的Session,直接Send
通過(guò)中轉(zhuǎn)服務(wù)器,或稱(chēng)為中心服務(wù)器進(jìn)行注冊(cè)/廣播
客戶(hù)端的model數(shù)據(jù)需要更新時(shí),服務(wù)器會(huì)主動(dòng)推送消息。
游戲服務(wù)器沒(méi)有嚴(yán)格的RPC設(shè)計(jì)需求,推送和單獨(dú)發(fā)送較Web服務(wù)器更多。而且游戲服務(wù)器多使用長(zhǎng)連接,所以主動(dòng)推送也比Web服務(wù)器來(lái)的方便一些。
Web:
將推送做成專(zhuān)有的服務(wù),并做排隊(duì)和并發(fā)處理。
可用性
聽(tīng)說(shuō)過(guò)游戲停服更新,支付寶服務(wù)器在刷二維碼時(shí)停服了可一定被罵慘吧。Web對(duì)服務(wù)器高可用性要求很高,游戲雖然也注重服務(wù)器穩(wěn)定性和可用性,但是由于版本迭代更新頻繁,停服更新反而能獲得玩家接受。
Game:
游戲?qū)捎眯砸蟛桓摺?/span>
游戲大版本更新時(shí)需要停服更新。支持熱更新技術(shù)的服務(wù)器(例如Erlang,Skynet)僅使用熱更新修復(fù)bug,很少直接更新新版本。
不是所有的游戲服務(wù)器支持動(dòng)態(tài)添加服務(wù)器。
Web:
極高的可用性,服務(wù)不允許停服更新,使用藍(lán)綠及灰度方式更新服務(wù)器。
隨時(shí)可以橫向擴(kuò)展服務(wù)器,提高服務(wù)器容量和承載。
連接及傳輸
均使用TCP傳輸協(xié)議,游戲服務(wù)器注重性能,自有協(xié)議及二進(jìn)制協(xié)議使用較多。
Web注重兼容和接口友好,使用JSON格式較多。
Game:
使用長(zhǎng)連接,需要從邏輯層維護(hù)連接狀態(tài)及處理服務(wù)器不在線(xiàn)情況
使用自有封包格式,大部分使用protobuf或二進(jìn)制流格式。
Web:
微服務(wù)大部分使用短連接,grpc支持http2長(zhǎng)連接
使用json編碼方便調(diào)試和版本兼容。
流量限制
人數(shù)多了,任何服務(wù)器都扛不住,流量限制和登入限制能有效保護(hù)服務(wù)器穩(wěn)定。
Game:
單服有人數(shù)限制,可以通過(guò)GM后臺(tái)設(shè)置擋墻,超過(guò)無(wú)法進(jìn)入
Web:
限流器中間件,可以精確到服務(wù)控制流量
斷流,防止雪崩
Game:
游戲沒(méi)有,也不需要這種概念,游戲請(qǐng)求不會(huì)突然升高,即便有,也通過(guò)GM后臺(tái)人為控制
Web:
斷流器中間件
服務(wù)發(fā)現(xiàn)
如何找到服務(wù)器地址。
服務(wù)有變化時(shí),通過(guò)Watch系統(tǒng)通知訂閱者更新本地緩存
服務(wù)器沒(méi)有變化時(shí),使用本地緩存找到服務(wù)地址
Game:
游戲服務(wù)器互相依賴(lài)復(fù)用只在很小的范圍內(nèi),因此無(wú)需在不同語(yǔ)言不同進(jìn)程服務(wù)間獲得地址,大部分在配置文件中填寫(xiě)各服務(wù)的IP及地址即可互相訪(fǎng)問(wèn)。
早期游戲自己編寫(xiě)服務(wù)器狀態(tài)及地址發(fā)現(xiàn)服務(wù)。
有用redis做服務(wù)發(fā)現(xiàn)
Web:
使用服務(wù)發(fā)現(xiàn)系統(tǒng),分布式部署。無(wú)需依賴(lài)配置文件
網(wǎng)關(guān)需求
Game:
網(wǎng)關(guān)處理客戶(hù)端上下線(xiàn)通知,心跳,維持連接,轉(zhuǎn)發(fā),廣播上下行封包
Web:
根據(jù)請(qǐng)求地址路由,無(wú)上下線(xiàn)概念,無(wú)心跳。廣播通過(guò)消息推送系統(tǒng)完成
由于筆者從事游戲行業(yè),對(duì)Web服務(wù)器概念在逐漸熟悉中,若有錯(cuò)誤和不足請(qǐng)各位大佬指出。
本人新書(shū)《Go語(yǔ)言從入門(mén)到進(jìn)階實(shí)戰(zhàn)》,生動(dòng)的語(yǔ)言,例子帶有各種彩蛋,輕松了解Go語(yǔ)言特性,更有cellnet框架剖析解密
https://search.jd.com/Search?keyword=go%E8%AF%AD%E8%A8%80%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E8%BF%9B%E9%98%B6%E5%AE%9E%E6%88%98&enc=utf-8&suggest=1.def.0.V02&wq=Go%E8%AF%AD%E8%A8%80%E4%BB%8E&pvid=145d55a92cab4b07b71326f8beb1700b
posted @ 2018-08-29 11:16 戰(zhàn)魂小筑 閱讀(2726) | 評(píng)論 (0)編輯 收藏

2017年12月19日 #

嵌套git庫(kù)的管理
使用git作為源代碼管理時(shí),經(jīng)常需要在一個(gè)git代碼庫(kù)中從外網(wǎng)獲取新的git庫(kù),也就是在git庫(kù)下嵌套另外一個(gè)git庫(kù)。而同時(shí)維護(hù)兩個(gè)git庫(kù)的過(guò)程就變的非常復(fù)雜。
submodule的弊端
常見(jiàn)的做法是使用git 提供的submodule功能。但submodule的管理嵌套git庫(kù)的結(jié)果往往不是我們期望的結(jié)果。假設(shè)有一個(gè)git庫(kù)叫project,在project的某個(gè)子目錄下還包含一個(gè)叫3rd的目錄,是另外一個(gè)git庫(kù)。
D:.
└─project
└─3rd
mytext.txt
假設(shè)甲和乙都取了project的代碼,由于時(shí)間差異,甲通過(guò)submodule取到V1版,而乙取到了V2版本。甲乙同時(shí)在不同的3rd庫(kù)下進(jìn)行開(kāi)發(fā),勢(shì)必會(huì)造成不同的運(yùn)行結(jié)果。也許你認(rèn)為可以在獲取submodule時(shí)指定版本,但這個(gè)獲取過(guò)程很難控制。
一般說(shuō)來(lái),第三方庫(kù)應(yīng)由主程序進(jìn)行更新及維護(hù),一般情況下,項(xiàng)目沒(méi)有特殊需求時(shí),不會(huì)隨便更新第三方庫(kù)到最新版本,因此submodule更新嵌套的git庫(kù)并不是理想的解決方案。
嵌套git庫(kù)的修改可見(jiàn)性
前面的例子中,project git庫(kù)下的3rd的git庫(kù)中如果有文件發(fā)生修改,此時(shí)在project目錄下,使用sourceTree等git管理工具無(wú)法識(shí)別3rd下的文件修改。
也就是說(shuō),無(wú)法將3rd下的修改提交到project的git庫(kù)中。
終極解決方案
此時(shí),將3rd目錄下的.git目錄暫時(shí)移出project和3rd目錄,此時(shí),在project目錄用sourceTree查看時(shí),將可以看到3rd下的文件修改,提交修改到project庫(kù)中。再將剛移出去的3rd的.git目錄移回3rd目錄下,在3rd目錄下使用git status,將可看到3rd目錄的修改,提交時(shí),會(huì)將修改提交到3rd目錄。
posted @ 2017-12-19 22:04 戰(zhàn)魂小筑 閱讀(3565) | 評(píng)論 (0)編輯 收藏

2017年11月27日 #

越來(lái)越多的人選擇用Mac或者Linux環(huán)境進(jìn)行跨平臺(tái)項(xiàng)目開(kāi)發(fā)。但是仍然有大部分人習(xí)慣于在Windows環(huán)境下進(jìn)行開(kāi)發(fā),畢竟Windows在各方面使用還是較為方便,特別像文件版本管理(Git,SVN等)

在跨平臺(tái)下開(kāi)發(fā)游戲或軟件,就需要有一套方便的自動(dòng)化工具。Windows下需要使用批處理,雖然有PowerShell加持,但這東西學(xué)了也不靠譜,只有一個(gè)平臺(tái)能用。大家還是習(xí)慣Linux Shell。連Mac平臺(tái)都可以用Shell,Windows上要做自動(dòng)化腳本就顯得非常尷尬。

我曾經(jīng)在項(xiàng)目中使用go編寫(xiě)了一套將配置轉(zhuǎn)為批處理和Linux Shell的工具。使用過(guò)程較為復(fù)雜,但是能跨平臺(tái)進(jìn)行表格導(dǎo)出和協(xié)議編譯等工作。

但是,這個(gè)工具還是需要對(duì)不同的平臺(tái)編寫(xiě)多套模板進(jìn)行代碼生成,非常繁瑣。如果有一套跨平臺(tái)的Shell,編寫(xiě)一次就可以跨平臺(tái)運(yùn)行那該多好。

查閱資料后,一共有幾個(gè)方案:

  1. 使用Python作為自動(dòng)化工具 這個(gè)方案其實(shí)就是使用python把批處理和Shell干的事情用代碼來(lái)解決。但前提是要重新學(xué)習(xí)Python,也需要一部分熟悉簡(jiǎn)單的Python語(yǔ)法,人為學(xué)習(xí)成本較高,也比較費(fèi)事。

  2. 自己編寫(xiě)一套獨(dú)立的自動(dòng)化工具 這個(gè)方案需要長(zhǎng)時(shí)間的適配過(guò)程,差什么指令補(bǔ)什么指令,對(duì)項(xiàng)目進(jìn)度有一定干擾。

  3. 自己編寫(xiě)Linux Shell的解釋器 這個(gè)就更難了,要做到100%兼容,基本不可能。

  1. 使用Cygwin和Mingw 需要一個(gè)微型運(yùn)行時(shí)進(jìn)行Linux Shell的解釋?zhuān)琺sys大概是18M左右,可行性較高。

在研究Cygwin和Mingw如何整合的過(guò)程中,我誤操作點(diǎn)擊了一個(gè)sh后綴的Linux Shell,這是我希望讓Mingw運(yùn)行的Shell。結(jié)果呢,sh后綴的文件居然能在Windows下運(yùn)行。我馬上編寫(xiě)了一系列的例子,發(fā)現(xiàn)幾乎完全兼容常用的Shell指令。 經(jīng)過(guò)研究,我發(fā)現(xiàn)Windows下能運(yùn)行sh文件是由Git自帶的msys2提供的。MSYS2 (Minimal SYStem 2, http://www.msys2.org/) 是一個(gè)MSYS的獨(dú)立改寫(xiě)版本,主要用于 shell 命令行開(kāi)發(fā)環(huán)境。同時(shí)它也是一個(gè)在Cygwin (POSIX 兼容性層) 和 MinGW-w64(從"MinGW-生成")基礎(chǔ)上產(chǎn)生的,追求更好的互操作性的 Windows 軟件。

那就是說(shuō),只要安裝了Git(https://git-scm.com/),那么就可以在Windows下直接運(yùn)行Linux Shell,只需要將文件后綴命名為sh即可

問(wèn)過(guò)周邊友人是否知道這一功能,都說(shuō)知道,只是沒(méi)有廣播而已,害我研究很久……

posted @ 2017-11-27 15:15 戰(zhàn)魂小筑 閱讀(5445) | 評(píng)論 (3)編輯 收藏

2017年7月6日 #

本文主要研究游戲服務(wù)器帶狀態(tài)的熱更新需求 http的無(wú)狀態(tài)熱更新需求已經(jīng)有成熟方案, 故不在本文描述范圍

基本概念

  • Golang的熱更新采用什么機(jī)制?

    使用go1.8提供的plugin包機(jī)制實(shí)現(xiàn)

  • plugin包本身設(shè)計(jì)的目的是熱更新么?

    plugin包其實(shí)只是支持將代碼分別編譯為多個(gè)動(dòng)態(tài)庫(kù),動(dòng)態(tài)加載后運(yùn)行 并不能完全支持類(lèi)似C/C++的動(dòng)態(tài)庫(kù)方式處理代碼

  • 帶狀態(tài)的進(jìn)程熱更新的基本概念及范圍是什么?

    數(shù)據(jù)部分(model)不更新, 只更新邏輯部分(函數(shù))

  • 表格和配置更新算熱更新么?

    算, 但不是本文描述范圍

  • 熱更新能在windows上使用么?

    不支持

代碼及結(jié)構(gòu)

  • 我能將原來(lái)一個(gè)exe的代碼編譯為so提供給plugin使用么?

    可以, 但是必須仍然保留main包作為插件入口, 并在main包內(nèi)添加提供給plugin調(diào)用入口.

  • 如果動(dòng)態(tài)庫(kù)中沒(méi)有main包, 編譯出的so能用么?

    不能, 包必須包含main, 否則輸出的是.a的文件, plugin包加載會(huì)報(bào)錯(cuò)

  • 動(dòng)態(tài)庫(kù)中, 非main包的的代碼修改能做熱更新么?

    不能!(崩潰了吧, 我提了一個(gè)issue: https://github.com/golang/go/issues/20554)

    如果確實(shí)做了修改, 底層會(huì)報(bào)錯(cuò): plugin was built with a different version of package

    解決方法: 修改plugin包底層實(shí)現(xiàn)并重新編譯 打開(kāi)runtime/plugin.go, 注釋以下代碼 for _, pkghash := range md.pkghashes { if pkghash.linktimehash != *pkghash.runtimehash { return "", nil, pkghash.modulename } } 執(zhí)行/usr/local/go/run.bash 重編譯+測(cè)試

  • 代碼中哪些可以被更新? 方法可以被更新么? 閉包呢?

    只能更新?lián)碛徐o態(tài)地址的結(jié)構(gòu).例如: 包級(jí)別函數(shù)(類(lèi)似于靜態(tài)函數(shù))

    例如: svc_0.so里有一個(gè)Foo函數(shù), svc_1.so修改了Foo函數(shù)實(shí)現(xiàn), 熱更新可實(shí)現(xiàn)

    閉包=函數(shù)+捕獲變量, 實(shí)際上是一個(gè)動(dòng)態(tài)結(jié)構(gòu), 沒(méi)有靜態(tài)地址, 無(wú)法被更新

    各種包級(jí)別變量, 結(jié)構(gòu)體變量, 結(jié)構(gòu)體方法, 局部變量均不能被熱更新, 但是變量值不會(huì)被影響

    新增結(jié)構(gòu)可以被運(yùn)行

  • 使用結(jié)構(gòu)體方法調(diào)用了包級(jí)別函數(shù), 包級(jí)別函數(shù)能被更新么?

    可以, 雖然方法不能被更新, 但方法被調(diào)用的包級(jí)別函數(shù)的地址是固定的, 所以可以被熱更新

  • init包初始化函數(shù)能用么? 能被熱更新么?

    官方這樣描述:

    When a plugin is first opened, the init functions of all packages not already part of the program are called. The main function is not run. A plugin is only initialized once, and cannot be closed

    插件第一次被打開(kāi)時(shí), 其關(guān)聯(lián)的, 沒(méi)有成為程序的一部分的所有的包的init函數(shù)將被調(diào)用. 插件的main函數(shù)不會(huì)被調(diào)用. 插件只會(huì)被初始化一次, 不能被關(guān)閉

    因此, 需要手動(dòng)將init函數(shù)改成自己的函數(shù), 統(tǒng)一在so的main包里調(diào)用

編譯

  • 如何編譯獲得plugin包支持的動(dòng)態(tài)庫(kù)

    SVCNAME=$1 SVCVER=$2 TIMESTAMP=`date '+%Y%m%d_%H%M%S'` go build -v -buildmode=plugin --ldflags="-pluginpath=${SVCNAME}_${TIMESTAMP}" -o ${SVCNAME}_${SVCVER}.so ${SVCNAME}

    -buildmode=plugin是重要參數(shù)

    --ldflags里的-pluginpath的作用是: 每次編譯的內(nèi)部識(shí)別路徑都是不同的, 避免重復(fù)加載的警告

    參考: https://github.com/golang/go/issues/19004

posted @ 2017-07-06 12:47 戰(zhàn)魂小筑 閱讀(8604) | 評(píng)論 (0)編輯 收藏

2017年4月20日 #

使用Visual Studio Code調(diào)試Golang工程

關(guān)鍵字

  • 最簡(jiǎn)單的調(diào)試攻略
  • 多項(xiàng)目調(diào)試, 適用個(gè)人開(kāi)發(fā)和項(xiàng)目開(kāi)發(fā)
  • 無(wú)需修改系統(tǒng)環(huán)境變量

準(zhǔn)備VSCode

在官網(wǎng)下載最新版的VSCode:

https://code.visualstudio.com/

安裝Golang插件

  • 打開(kāi)擴(kuò)展面板

    VSCode->查看->擴(kuò)展

  • 找到Go插件 在搜索框里輸入Go, 找到第二行寫(xiě)有 Rich Go language support for Visual Studio Code的插件, 點(diǎn)擊安裝

    注意不是排名最高的

  • 重啟編輯器

配置啟動(dòng)項(xiàng)

  • 打開(kāi)調(diào)試面板

    VSCode->查看->調(diào)試

  • 添加調(diào)試目標(biāo)

    在"沒(méi)有調(diào)試"的下拉框中點(diǎn)擊"添加配置.."

  • 添加目標(biāo)調(diào)試配置

    例子:

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "Launch",
                "type": "go",
                "request": "launch",
                "mode": "debug",
                "remotePath": "",
                "port": 2345,
                "host": "127.0.0.1",
                "program": "${fileDirname}",
                "env": {
                    "GOPATH":"D:/Develop/vscodegolang"
                },
                "args": [],
                "showLog": true
            }
        ]
    }

其中: "port", "host"都是go插件自動(dòng)生成的

"env"為設(shè)置環(huán)境變量, 設(shè)置為你的工程目錄就可以(包含bin, src的文件夾)

準(zhǔn)備調(diào)試插件

此時(shí)找到main.go按F5, 會(huì)報(bào)錯(cuò)提示:

Failded to continue:"Cannot find Delve debugger. Install from https://github.com/derekparker/delve & ensure it is in your "GOPATH/bin" or "PATH"

我們使用go命令行編譯調(diào)試器

go get github.com/derekparker/delve/cmd/dlv

將dlv調(diào)試器放在GOPATH(工程目錄)的bin目錄下

開(kāi)始調(diào)試

選中要調(diào)試的main.go, 點(diǎn)擊F5, 既可以開(kāi)始調(diào)試

調(diào)試快捷鍵和Visual Studio系一致

  • F9 切換斷點(diǎn)
  • F10 Step over
  • F11 Step in
  • Shift+F11 Step out

注意點(diǎn)

  • 某些結(jié)構(gòu)體成員無(wú)法直接顯示時(shí), 可以直接選中變量名, 添加到監(jiān)視, 或者右鍵點(diǎn)擊: "調(diào)試:求值"

多項(xiàng)目調(diào)試

在launch.json中可以添加多組調(diào)試入口, 通過(guò)調(diào)試面板中選中對(duì)應(yīng)的配置開(kāi)啟不同目標(biāo)的調(diào)試

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "client",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "remotePath": "",
            "port": 2345,
            "host": "127.0.0.1",
            "program": "${fileDirname}",
            "env": {
                "GOPATH":"D:/Develop/vscodegolang"
            },
            "args": [],
            "showLog": true
        },

        {
            "name": "server",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "remotePath": "",
            "port": 2345,
            "host": "127.0.0.1",
            "program": "${workspaceRoot}/src/server",
            "env": {
                "GOPATH":"D:/Develop/vscodegolang"
            },
            "args": [],
            "showLog": true
        }
    ]
}

"program"中的"${fileDirname}"是以當(dāng)前選中文件作為啟動(dòng)點(diǎn)

更建議使用"program"的"${workspaceRoot}", 以包名作為啟動(dòng)點(diǎn)的方式進(jìn)行配置

參考鏈接

https://code.visualstudio.com/Docs/editor/debugging

posted @ 2017-04-20 12:52 戰(zhàn)魂小筑 閱讀(8319) | 評(píng)論 (0)編輯 收藏

2017年4月8日 #

相位技術(shù)

相位技術(shù)大規(guī)模出現(xiàn)在魔獸世界WLK版本, 現(xiàn)在應(yīng)用已經(jīng)廣泛應(yīng)用在各種MMORPG游戲中. 下面對(duì)相位技術(shù)的做法進(jìn)行簡(jiǎn)單歸納匯總

表現(xiàn)分類(lèi)

副本相位

早期副本的出現(xiàn), 避免搶怪問(wèn)題. 所以, 副本其實(shí)本身就是一種相位技術(shù). 只不過(guò)實(shí)現(xiàn)時(shí), 我們一般會(huì)將小隊(duì)和怪物直接預(yù)分配在獨(dú)立的一個(gè)副本實(shí)例中(所以副本原文也是實(shí)例的意思)

分線(xiàn)相位

相位技術(shù)還沒(méi)有正式命名時(shí), 同一個(gè)場(chǎng)景, 玩家進(jìn)到不同的分線(xiàn)看到的玩家不一樣, 也是屬于相位的一種. 當(dāng)然, 如果是組隊(duì)玩家, 服務(wù)器默認(rèn)會(huì)分配所有隊(duì)伍玩家在同一個(gè)線(xiàn)(位面)

真相位

副本相位和分線(xiàn)相位其實(shí)都是靜態(tài)相位, 一旦進(jìn)入, 中途不會(huì)有切換或者混合查看的過(guò)程. 真相位可以在一個(gè)場(chǎng)景中,動(dòng)態(tài)切換相位, 相位內(nèi)和相位外所以不同

我們常見(jiàn)的真相位表現(xiàn)為: 相位中的角色+玩家+隊(duì)伍成員

在護(hù)送任務(wù)時(shí), 還會(huì)在上面所見(jiàn)角色中疊加世界中的所有角色, 也就是說(shuō), 你和隊(duì)伍成員可以看到的角色, 其他人看不到, 其他人也看不到你和你的隊(duì)伍成員


為了清晰的簡(jiǎn)單的描述, 我為相位創(chuàng)建如下概念與名詞

相位客體

表現(xiàn)為除玩家外的角色(怪物,交互物體與相位可見(jiàn)場(chǎng)景)

私有客體

這是最常見(jiàn)的一種相位內(nèi)角色

  • 持有變量

    取PhasingID時(shí),為PhasingTargetID

  • 生成規(guī)則

    當(dāng)玩家開(kāi)啟相位后, 在玩家相位內(nèi)生成的角色為私有客體.

    此時(shí), 將 PhasingTargetID設(shè)置為相位生成者的實(shí)例ID

  • 刪除規(guī)則

    如果玩家退出相位, 私有客體會(huì)存在一段時(shí)間或按照需求刪除

公共客體

一般指提前放置在場(chǎng)景中, 世界內(nèi)不可見(jiàn), 但是能被同相位玩家可見(jiàn),且同相位玩家都可以互相可見(jiàn) 比如: 只要接了同一個(gè)任務(wù)的玩家, 都可以看到的NPC

  • 持有變量

    取PhasingID時(shí),為PublicPhasingID

  • 生成規(guī)則

    通過(guò)場(chǎng)景編輯器, 放置角色時(shí), 設(shè)置其可被觀(guān)察到的任務(wù)ID

    角色被加載后, 將任務(wù)ID設(shè)置到StaticPhasingID

  • 刪除規(guī)則

    場(chǎng)景刪除, 角色刪除

相位主體

包含玩家與同隊(duì)伍玩家

  • 開(kāi)啟相位后, 可見(jiàn)私有客體+公有客體

  • 隊(duì)長(zhǎng)視為相位主體, 單人時(shí), 自己為隊(duì)長(zhǎng)

  • 隊(duì)伍其他成員共享隊(duì)長(zhǎng)的私有相位客體

  • 隊(duì)伍其他成員根據(jù)自己的PublicPhasingID匹配目標(biāo)對(duì)象的PublicPhasingID時(shí)可互相可見(jiàn)

  • 持有變量

相位開(kāi)啟時(shí), 取PhasingID時(shí), 為角色實(shí)例ID

相位關(guān)閉時(shí), 取PhasingID時(shí), 為0

PublicPhasingID

可見(jiàn)規(guī)則

當(dāng)兩個(gè)角色的PhasingID相等時(shí), 主體與私有客體互相可見(jiàn)

當(dāng)兩個(gè)角色的PublicPhasingID相等時(shí), 主體與公有客體互相可見(jiàn)

可以通過(guò)開(kāi)關(guān)設(shè)置, 是否在可見(jiàn)的相位客體基礎(chǔ)上, 疊加世界角色(護(hù)送任務(wù))

約束

  • 玩家同時(shí)只能看見(jiàn)1個(gè)相位
posted @ 2017-04-08 14:41 戰(zhàn)魂小筑 閱讀(21320) | 評(píng)論 (0)編輯 收藏

2016年12月1日 #

Golang中沒(méi)有設(shè)計(jì)構(gòu)造函數(shù). 取而代之的, 設(shè)計(jì)Golang的大師希望你用普通函數(shù)去實(shí)現(xiàn)構(gòu)造的任務(wù). 
一直只是覺(jué)得這只是體現(xiàn)Golang這門(mén)新語(yǔ)言的精簡(jiǎn)設(shè)計(jì)之道, 直到自己實(shí)現(xiàn)編譯器后才發(fā)現(xiàn)構(gòu)造函數(shù)的設(shè)計(jì)本身是值得商榷的

我們先看下構(gòu)造函數(shù)的規(guī)則

構(gòu)造函數(shù)調(diào)用規(guī)則

構(gòu)造參數(shù)量: 0表示沒(méi)有構(gòu)造函數(shù), 1表示有構(gòu)造函數(shù)0個(gè)參數(shù)

本類(lèi)構(gòu)造父類(lèi)構(gòu)造處理方法
00不處理
10調(diào)本類(lèi)ctor
01調(diào)父類(lèi)ctor
11調(diào)本類(lèi)ctor, 本類(lèi)ctor調(diào)父類(lèi)ctor
21調(diào)本類(lèi)ctor, 本類(lèi)ctor調(diào)父類(lèi)ctor
12報(bào)錯(cuò), 手動(dòng)調(diào)父類(lèi)ctor
22報(bào)錯(cuò), 手動(dòng)調(diào)父類(lèi)ctor

普通函數(shù)重載規(guī)則

實(shí)際只用考慮最典型的一種行為: 實(shí)例化子類(lèi), 轉(zhuǎn)為父類(lèi)調(diào)用方法, 這個(gè)時(shí)候

如果方法是override, 調(diào)用的是子類(lèi)

如果方法是virutal或者不指明, 調(diào)用的是父類(lèi)

整個(gè)重載過(guò)程, 子類(lèi)絕對(duì)不會(huì)隱式調(diào)用父類(lèi)的行為

需要構(gòu)造函數(shù)么?

構(gòu)造函數(shù)的優(yōu)點(diǎn)

  • 本身屬于一種特殊的成員函數(shù)
  • 編譯器幫你自動(dòng)傳導(dǎo)調(diào)用父級(jí)

構(gòu)造函數(shù)的缺點(diǎn)

  • 隱式的調(diào)用規(guī)則
  • 雖然屬于成員函數(shù), 但是與其他成員函數(shù)調(diào)用規(guī)則完全不同, 需要特殊記憶
  • 帶參數(shù)的構(gòu)造函數(shù), 在父類(lèi)參數(shù)多于子類(lèi)時(shí), 需要引用復(fù)雜語(yǔ)法來(lái)實(shí)現(xiàn)父級(jí)構(gòu)造調(diào)用

其實(shí)我們對(duì)初始化函數(shù)的需求只有1條: 自定義

所以, 可以理解Golang不加入構(gòu)造函數(shù)的設(shè)計(jì)是正確的 
即: 簡(jiǎn)單, 清晰, 有規(guī)律

posted @ 2016-12-01 10:45 戰(zhàn)魂小筑 閱讀(3369) | 評(píng)論 (0)編輯 收藏

2016年11月2日 #

append, map, len不是關(guān)鍵字

他們其實(shí)還是類(lèi)庫(kù)功能, 都在buildin包里的, 系統(tǒng)默認(rèn)給你做了個(gè)

  1. import(
  2. . "buildin"
  3. )

將buildin的包內(nèi)容都映射到全局而已, 其實(shí)你也可以用自己的包這么做

打印的另一種寫(xiě)法

想跟腳本一樣調(diào)試打印數(shù)據(jù)么?

  1. println("hello world")

無(wú)需包含任何包, 因?yàn)樗赽uildin包里

iota不是黑科技

這是在buildin包里的定義

  1. // iota is a predeclared identifier representing the untyped integer ordinal
  2. // number of the current const specification in a (usually parenthesized)
  3. // const declaration. It is zero-indexed.
  4. const iota = 0 // Untyped int.

其實(shí)go是有泛型概念的

想想map和數(shù)組的定義 
只是泛型沒(méi)有開(kāi)放給用戶(hù)用而已(只許XX放火,不許XX點(diǎn)燈)

map是支持多個(gè)key的, 而且很方便

還在為多個(gè)key轉(zhuǎn)id的復(fù)雜算法而頭疼么?

  1. type myKey struct{
  2. number int
  3. str string
  4. }
  5. func main(){
  6. t := map[ myKey] int {
  7. myKey{ 2, "world"}: 1,
  8. }
  9. fmt.Println(t[myKey{2, "world"}])
  10. }
  11. 輸出: 1

枚舉是可以轉(zhuǎn)成string的

默認(rèn)定義一個(gè)枚舉

  1. type MyConst int
  2. const (
  3. MyConst_A MyConst = iota
  4. MyConst_B MyConst = iota
  5. )
  6. func main(){
  7. fmt.Println(MyConst_A)
  8. }

輸出: 0 
如果我們想自動(dòng)化輸出MyConst_A字符串時(shí) 
就需要使用golang的一個(gè)工具鏈:golang.org/x/tools/cmd/stringer 
將其下載, 編譯成可執(zhí)行工具后, 對(duì)代碼進(jìn)行生成 
生成的代碼會(huì)多出一個(gè)xx_string.go 
里面就是枚舉的String()string 函數(shù)

臨時(shí)轉(zhuǎn)換一個(gè)接口并調(diào)用的方法

  1. type love struct{
  2. }
  3. func (self*love)foo(){
  4. fmt.Println("love")
  5. }
  6. func main(){
  7. var chaos interface{} = new(love)
  8. chaos.(interface{
  9. foo()
  10. }).foo()
  11. }

Golang的receiver實(shí)際上就是this的變種實(shí)現(xiàn)

  1. func( self*MyStruct) foo( p int ){
  2. }

寫(xiě)不慣receiver的寫(xiě)法? 如果這樣改下呢?

  1. func foo( self *MyStruct, p int ){
  2. }

所以為什么說(shuō)Golang還是一個(gè)C語(yǔ)言嘛

關(guān)于內(nèi)存分配…

  • new 傳入Type類(lèi)型, 返回*Type類(lèi)型
  • make 可以在分配數(shù)組時(shí)設(shè)置預(yù)分配大小, new不可以
  • make 能分配數(shù)組,map, 但不能分配結(jié)構(gòu)體和原始類(lèi)型
  • new 能分配數(shù)組, map, 結(jié)構(gòu)體和原始類(lèi)型等的所有類(lèi)型
  • &Type等效于new
  • 切片不需要分配內(nèi)存(make,new), 直接聲明就可以了…

Golang的反射無(wú)法通過(guò)一個(gè)類(lèi)型名, 創(chuàng)建其實(shí)例

C#有Assembly概念, 可以在一個(gè)Assembly里搜索, 創(chuàng)建實(shí)例

Golang是靜態(tài)類(lèi)型語(yǔ)言, 如果需要, 只能注冊(cè)你需要?jiǎng)?chuàng)建的結(jié)構(gòu)體, 然后將注冊(cè)好的map用于創(chuàng)建

Golang可以替換Python來(lái)進(jìn)行復(fù)雜的工具流程處理

如果你需要跨平臺(tái)的工具流程處理, 對(duì)Python不熟悉, 可以使用

  1. go run yourcode.go 參數(shù)1 參數(shù)2

方式來(lái)進(jìn)行工具處理 
覺(jué)得慢, 可以編譯成可執(zhí)行文件

這樣做的好處: 如果有些類(lèi)庫(kù)本身就是go寫(xiě)的, Python想使用是很麻煩的, 而Golang來(lái)寫(xiě)則輕而易舉

例子: 通過(guò)go的protobuf庫(kù), 對(duì)一些文件進(jìn)行處理

Golang可以自動(dòng)持有方法的接收者實(shí)例

  1. type myType struct{
  2. }
  3. func (self*myType) foo( p int){
  4. fmt.Println("hello", p )
  5. }
  6. func main(){
  7. var callback func( int )
  8. ins := new(myType)
  9. callback = ins.foo
  10. callback( 100 )
  11. }

做過(guò)lua的C++代碼綁定的童鞋都清楚: lua只支持外部靜態(tài)或者全局函數(shù)調(diào)用 
如果要進(jìn)行C++類(lèi)成員函數(shù)調(diào)用時(shí), 要自己處理this和成員函數(shù) 
這種技巧因?yàn)樵缙鹁幾g器的虛表不同平臺(tái)實(shí)現(xiàn)細(xì)節(jié)不統(tǒng)一需要專(zhuān)門(mén)處理 
后面跨平臺(tái)虛表統(tǒng)一后, 類(lèi)成員函數(shù)的調(diào)用寫(xiě)法也是很惡心復(fù)雜的 
但是Golang的小白式用法, 直接吊打C++, 甚至C#復(fù)雜的delegate

LiteIDE篇: 多開(kāi)秘籍

  • 找到 菜單->查看->選項(xiàng)->通用->存儲(chǔ)->存儲(chǔ)設(shè)置到本地ini文件

  • 關(guān)閉LiteIDE

  • 復(fù)制LiteIDE整個(gè)目錄, 命名文件夾為你的工程名

  • 每個(gè)工程所在的LiteIDE的配置將是獨(dú)立的, 不會(huì)互相干擾

LiteIDE篇: 測(cè)試程序也是可以調(diào)試的

別以為程序一定要是main開(kāi)始的才可以調(diào)試

Golang的測(cè)試程序雖然都是一個(gè)個(gè)Test開(kāi)頭的函數(shù),但執(zhí)行g(shù)o test時(shí), 還是有main入口

在LiteIDE中, 可以在 調(diào)試->開(kāi)始調(diào)試測(cè)試程序里進(jìn)行測(cè)試程序調(diào)試

LiteIDE篇: 在Windows上可以輸出linux可執(zhí)行文件

go的工具鏈默認(rèn)支持交叉編譯 
在LiteIDE中, 可以通過(guò)切換輸出平臺(tái), 輸出不同平臺(tái)的可執(zhí)行文件

posted @ 2016-11-02 11:09 戰(zhàn)魂小筑 閱讀(23258) | 評(píng)論 (1)編輯 收藏

2016年9月3日 #

Google官方為Golang的調(diào)試?yán)幽J(rèn)使用了gdb

然而, 使用gdb調(diào)試go程序會(huì)遇到goroutine的各類(lèi)問(wèn)題, 因?yàn)間db不懂go

因此, 這里使用delve黑科技來(lái)進(jìn)行Golang的程序調(diào)試

純命令行調(diào)試方法在網(wǎng)上很容易搜索到, 本文主要以L(fǎng)iteIDE來(lái)進(jìn)行程序調(diào)試

關(guān)閉編譯器優(yōu)化

正常go build/install出的go程序是完全優(yōu)化過(guò)的, 強(qiáng)行使用調(diào)試器掛接調(diào)試時(shí), 某些local變量/lamda表達(dá)式捕獲的變量會(huì)直接進(jìn)入寄存器, 無(wú)法使用調(diào)試器查看

刪掉所有的pkg, 為build或install參數(shù)加入關(guān)閉編譯器優(yōu)化的參數(shù) -gcflags "-N -l"

例如:

  1. go install -gcflags "-N -l" svc\gamesvc

delve調(diào)試器安裝方法

LiteIDE自帶了gdb, 但是沒(méi)有delve調(diào)試器, 需要自行安裝, 命令如下

  1. go get github.com/derekparker/delve/cmd/dlv

delve調(diào)試器會(huì)被放到你的GOPATH/bin下

LiteIDE中的delve調(diào)試器配置

選擇調(diào)試器

在LiteIDE菜單中選擇 調(diào)試->debugger/delve

delve環(huán)境變量設(shè)置

這個(gè)時(shí)候, LiteIDE依然找不到delve, 因?yàn)樗辉诃h(huán)境變量PATH中, 這里無(wú)需修改環(huán)境變量, 只需要LiteIDE的環(huán)境配置

在LiteIDE菜單中選擇 查看->編輯當(dāng)前環(huán)境, 在彈出的文檔中修改

  1. PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH%;c:\your\path\to\delve

去掉PATH前的注釋#, 在%PATH%添加分號(hào), 然后和你到delve調(diào)試器的路徑

開(kāi)始調(diào)試

選擇你的工程, 點(diǎn)擊F5, 進(jìn)入調(diào)試模式

調(diào)試器顯示變量值

LiteIDE使用delve調(diào)試時(shí), 無(wú)法在 變量 監(jiān)視等窗口中正確捕捉delve調(diào)試返回?cái)?shù)據(jù)(因?yàn)楦袷教珡?fù)雜了…)

沒(méi)關(guān)系, 我們使用命令行配合顯示即可

LiteIDE控制臺(tái)或調(diào)試輸出窗口在delve調(diào)試時(shí), 實(shí)際上是一個(gè)標(biāo)準(zhǔn)命令行 
命令如下

  • p 變量名可以查看變量值

  • locals查看局部變量

  • ls可查看當(dāng)前文件

  • stack查看棧

  • help可以查看各種幫助

調(diào)試外部程序

如果你的程序是外部程序, 或者使用go install安裝到GOPATH/bin目錄的程序, 那么使用delve調(diào)試器啟動(dòng)程序時(shí), 可能會(huì)碰到啟動(dòng)路徑錯(cuò)誤的問(wèn)題

使用LiteIDE菜單 調(diào)試->調(diào)試其他應(yīng)用程序… 填入你要調(diào)試程序的路徑以及工作目錄, 可以解決這個(gè)問(wèn)題

posted @ 2016-09-03 18:12 戰(zhàn)魂小筑 閱讀(5593) | 評(píng)論 (0)編輯 收藏

僅列出標(biāo)題  下一頁(yè)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美精品一区二区三区蜜桃 | 久久国产精品一区二区三区四区| 亚洲国产精品传媒在线观看 | 黄色小说综合网站| 国产亚洲综合在线| 樱桃国产成人精品视频| 亚洲国产欧美精品| 一区二区三区高清在线| 亚洲欧美日韩久久精品| 久久精品成人一区二区三区| 老司机午夜精品视频| 亚洲国产精品国自产拍av秋霞| 亚洲福利视频网| 一二三区精品| 久久精品免视看| 欧美大片91| 国产欧美日韩视频一区二区| 亚洲国产一区在线| 亚洲综合日韩中文字幕v在线| 久久久久99| 亚洲精品自在在线观看| 亚洲在线电影| 欧美jizzhd精品欧美巨大免费| 国产精品户外野外| 亚洲区免费影片| 一本色道久久综合精品竹菊| 欧美一区不卡| 欧美理论电影网| 国产亚洲精品aa| 亚洲午夜精品视频| 亚洲在线视频网站| 激情亚洲成人| 亚洲美女中出| 久久九九精品99国产精品| 欧美电影免费| 亚洲欧美亚洲| 欧美日韩精品一二三区| 尤物在线精品| 久久国产日韩欧美| 一区二区三区av| 美女主播一区| 国内揄拍国内精品久久| 亚洲小视频在线观看| 欧美黑人在线观看| 久久久久久网| 激情视频亚洲| 久久av二区| 亚洲天堂av在线免费观看| 欧美另类亚洲| 亚洲精品在线免费| 欧美激情亚洲自拍| 老司机免费视频一区二区三区| 国产欧美日本一区二区三区| 亚洲一级网站| 99这里只有精品| 欧美日韩三级电影在线| 99国产精品久久久| 亚洲国产网站| 欧美成人综合一区| 99视频精品在线| 日韩视频不卡中文| 欧美三级电影一区| 亚洲性xxxx| 亚洲婷婷免费| 国产日韩综合一区二区性色av| 香蕉av777xxx色综合一区| 一区二区三区国产盗摄| 国产精品国产亚洲精品看不卡15| 中文亚洲视频在线| 亚洲综合日韩在线| 国产日韩欧美在线播放不卡| 久久九九国产| 美女脱光内衣内裤视频久久网站| 亚洲三级免费观看| 99精品欧美一区二区三区| 国产精品成人一区二区网站软件 | 欧美人与禽猛交乱配视频| 一区二区欧美日韩| 在线视频欧美日韩| 欧美精品videossex性护士| 一区二区三区在线视频免费观看| 蜜桃视频一区| 欧美日韩国产色站一区二区三区| 亚洲第一伊人| 亚洲国产女人aaa毛片在线| 欧美成人精品一区二区| 亚洲午夜视频在线观看| 午夜精品三级视频福利| 在线观看一区| 夜夜精品视频一区二区| 国产亚洲欧美另类一区二区三区| 免播放器亚洲一区| 欧美精品性视频| 久久高清福利视频| 欧美成人按摩| 欧美在线视频一区二区三区| 蜜臀91精品一区二区三区| 亚洲专区一区二区三区| 久久综合久久综合九色| 亚洲欧美综合一区| 久久久美女艺术照精彩视频福利播放| 欧美中文日韩| 国产精品99久久久久久白浆小说| 欧美一区高清| 一区二区三区毛片| 久久激情网站| 亚洲欧美综合| 欧美精品aa| 麻豆精品在线视频| 国产精品入口日韩视频大尺度| 免费在线日韩av| 国产精品美女久久久久久久| 亚洲国产一区二区a毛片| 狠狠色综合网站久久久久久久| 一区二区日韩精品| 日韩一级不卡| 免费人成网站在线观看欧美高清| 欧美中文字幕| 国产精品久久国产三级国电话系列| 欧美大片在线看| 黄色成人91| 性伦欧美刺激片在线观看| 一本色道久久综合狠狠躁篇的优点| 久久久久久久91| 久久精品在线播放| 国产精品私拍pans大尺度在线 | 国产精品一二一区| 999亚洲国产精| 日韩一级大片在线| 农村妇女精品| 亚洲国产精品久久久久婷婷884 | 亚洲精选中文字幕| 久久五月激情| 免费观看在线综合色| 国模精品一区二区三区| 亚洲欧美激情视频| 久久av一区二区三区| 国产伦精品一区二区三区高清版| 亚洲天堂成人| 久久精品国产清高在天天线 | 国产精品视频免费一区| 欧美电影在线| 亚洲盗摄视频| 老色批av在线精品| 欧美成人精品1314www| 91久久精品日日躁夜夜躁国产| 夜夜嗨av一区二区三区四季av| 欧美电影免费观看高清| 最新高清无码专区| 一区二区三区精品视频在线观看| 欧美高清不卡| 宅男精品导航| 亚洲综合社区| 一区视频在线播放| 亚洲国产mv| 欧美视频在线观看一区| 亚洲欧美日韩一区二区三区在线观看 | 日韩视频免费观看| 欧美国产精品久久| 亚洲精品自在在线观看| 一区二区三区福利| 欧美成人免费在线视频| 久久久久久尹人网香蕉| 欧美国产一区二区| 99人久久精品视频最新地址| 欧美一区二粉嫩精品国产一线天| 国产模特精品视频久久久久| 久久精品一区二区三区不卡牛牛| 亚洲高清不卡在线观看| 亚洲一二三四区| 精品va天堂亚洲国产| 欧美精品久久久久a| 亚洲欧美乱综合| 亚洲国产欧美一区| 久久国内精品自在自线400部| 亚洲国产毛片完整版 | 欧美成人69| 午夜精品久久久久久久99樱桃| 久久在线观看视频| 亚洲图片欧洲图片av| 亚洲成色999久久网站| 国产精品久久9| 久热爱精品视频线路一| 亚洲午夜久久久| 亚洲国产人成综合网站| 国产亚洲欧美日韩日本| 亚洲视频精选| 国产欧美日韩免费看aⅴ视频| 免费黄网站欧美| 亚洲一线二线三线久久久| 亚洲成色精品| 欧美日韩在线视频一区二区| 亚洲欧美日韩中文视频| 91久久久亚洲精品| 麻豆亚洲精品| 久久久美女艺术照精彩视频福利播放 | 亚洲国产天堂久久国产91| 国产精品一区二区在线观看不卡 | 亚洲免费观看高清在线观看| 另类专区欧美制服同性|