import "workname/packetfolder"
創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)和樂山服務(wù)器托管的網(wǎng)絡(luò)公司,有著豐富的建站經(jīng)驗(yàn)和案例。
導(dǎo)入多個(gè)包
方法調(diào)用 包名.函數(shù)//不是函數(shù)或結(jié)構(gòu)體所處文件或文件夾名
packagename.Func()
前面加個(gè)點(diǎn)表示省略調(diào)用,那么調(diào)用該模塊里面的函數(shù),可以不用寫模塊名稱了:
當(dāng)導(dǎo)入一個(gè)包時(shí),該包下的文件里所有init()函數(shù)都會(huì)被執(zhí)行,然而,有些時(shí)候我們并不需要把整個(gè)包都導(dǎo)入進(jìn)來,僅僅是是希望它執(zhí)行init()函數(shù)而已。下劃線的作用僅僅是為了調(diào)用init()函數(shù),所以無法通過包名來調(diào)用包中的其他函數(shù)
import _ package
變量聲明必須要使用否則會(huì)報(bào)錯(cuò)。
全局變量運(yùn)行聲明但不使用。
func 函數(shù)名 (參數(shù)1,參數(shù)2,...) (返回值a 類型a, 返回值b 類型b,...)
func 函數(shù)名 (參數(shù)1,參數(shù)2,...) (返回值類型1, 返回值類型2,...)
func (this *結(jié)構(gòu)體名) 函數(shù)名(參數(shù) string) (返回值類型1, 返回值類型2){}
使用大小來區(qū)分函數(shù)可見性
大寫是public類型
小寫是private類型
func prifunc int{}
func pubfunc int{}
聲明靜態(tài)變量
const value int
定義變量
var value int
聲明一般類型、接口和結(jié)構(gòu)體
聲明函數(shù)
func function () int{}
go里面所有的空值對(duì)應(yīng)如下
通道類型
內(nèi)建函數(shù) new 用來分配內(nèi)存,它的第一個(gè)參數(shù)是一個(gè)類型,不是一個(gè)值,它的返回值是一個(gè)指向新分配類型零值的指針
func new(Type) *Type
[這位博主有非常詳細(xì)的分析]
Go 語言支持并發(fā),我們只需要通過 go 關(guān)鍵字來開啟 goroutine 即可。
goroutine 是輕量級(jí)線程,goroutine 的調(diào)度是由 Golang 運(yùn)行時(shí)進(jìn)行管理的。
同一個(gè)程序中的所有 goroutine 共享同一個(gè)地址空間。
語法格式如下:
通道(channel)是用來傳遞數(shù)據(jù)的一個(gè)數(shù)據(jù)結(jié)構(gòu)。
通道的聲明
通道可用于兩個(gè) goroutine 之間通過傳遞一個(gè)指定類型的值來同步運(yùn)行和通訊。操作符 - 用于指定通道的方向,發(fā)送或接收。如果未指定方向,則為雙向通道。
[這里有比較詳細(xì)的用例]
go里面的空接口可以指代任何類型(無論是變量還是函數(shù))
聲明空接口
go里面的的強(qiáng)制類型轉(zhuǎn)換語法為:
int(data)
如果是接口類型的強(qiáng)制轉(zhuǎn)成其他類型的語法為:
go里面的強(qiáng)制轉(zhuǎn)換是將值復(fù)制過去,所以在數(shù)據(jù)量的時(shí)候有比較高的運(yùn)行代價(jià)
任何一門計(jì)算機(jī)語言,都能在特定某個(gè)領(lǐng)域的應(yīng)用中,實(shí)現(xiàn)區(qū)塊鏈技術(shù);
具體使用哪一門語言,完全看我們相應(yīng)領(lǐng)域行業(yè)企業(yè)項(xiàng)目的技術(shù)要求,以及更關(guān)鍵的:跟已有信息系統(tǒng)的有效對(duì)接聯(lián)通。
區(qū)塊鏈具有自下而上生成記錄,生成兩方或多方合同類記錄,加入第三方確認(rèn)機(jī)制,分布存儲(chǔ),……等特點(diǎn);
從而讓它相比集中式的存儲(chǔ)運(yùn)算而言,變得更為可信。
常見的總統(tǒng)投票,就非常適合以區(qū)塊鏈技術(shù)重新架構(gòu);采用區(qū)塊鏈技術(shù)的投票系統(tǒng),能夠避免哪一家技術(shù)公司、某一個(gè)關(guān)鍵技術(shù)人員,操縱選票統(tǒng)計(jì)結(jié)果的可能。
像我們的法院證據(jù),也特別適合采用區(qū)塊鏈技術(shù)重新架構(gòu)開發(fā)。
其實(shí)像當(dāng)前我們各類互聯(lián)網(wǎng)時(shí)代的“版權(quán)系統(tǒng)”,它們中一些就是采用區(qū)塊鏈技術(shù)架構(gòu)而來,只不過,目前我們的新聞出版局、專利局(或者更廣義地被稱作“專家評(píng)委”),都尚未接入這些由互聯(lián)網(wǎng)公司創(chuàng)新而來的版權(quán)平臺(tái)。
我們耳熟能詳 的“法大大”(雖然名字不甚好聽、甚至乍一聽來有些讓人“摸不著頭腦”),它也其實(shí)正準(zhǔn)備采用最新的區(qū)塊鏈技術(shù)重新架構(gòu);采用區(qū)塊鏈技術(shù)的合同平臺(tái),因?yàn)樽兊酶涌尚?,也才能更便于互?lián)網(wǎng)時(shí)代人們簽訂各類商務(wù)合同。
還有像我們的“征信系統(tǒng)”,也非常適合以區(qū)塊鏈技術(shù)加以改造。能夠讓它更有說服力,而不致于出現(xiàn)一家單位、乃至隨意某個(gè)關(guān)鍵技術(shù)人員,能隨意往其中添加“征信污點(diǎn)數(shù)據(jù)”的情況。
還有像我們的P2P貸款,如果能夠以區(qū)塊鏈技術(shù)重新架構(gòu)的話,也能夠變得更加可信,而不致于出現(xiàn)違約、卷款跑路這樣的失信情況。
繼續(xù)進(jìn)入下一個(gè)初始化
n.netService, err = nebnet.NewNebService(n)
if err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup net service.")
}
netservice有兩個(gè)成員
type NebServicestruct {
node? ? ? *Node
dispatcher *Dispatcher
}
跳出stup()函數(shù)
先進(jìn)入start()函數(shù)看一看
if err := n.netService.Start(); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to start net service.")
}
進(jìn)入netservice.start()
func (ns *NebService) Start() error {
logging.CLog().Info("Starting NebService...")
// start dispatcher.
ns.dispatcher.Start()
// start node.
if err := ns.node.Start(); err != nil {
ns.dispatcher.Stop()
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Error("Failed to start NebService.")
return err
}
logging.CLog().Info("Started NebService.")
return nil
}
可以看到第一個(gè)start()的函數(shù)是dispatcher.start()
進(jìn)入dispatch.start()
func (dp *Dispatcher) Start() {
logging.CLog().Info("Starting NebService Dispatcher...")
go dp.loop()
}
然后就出現(xiàn)一個(gè)新的線程、goruntime
go dp.loop()
進(jìn)入該線程,看它干了些什么
timerChan := time.NewTicker(time.Second).C
for {
select {
case -timerChan:
metricsDispatcherCached.Update(int64(len(dp.receivedMessageCh)))
case -dp.quitCh:
logging.CLog().Info("Stoped NebService Dispatcher.")
return
case msg := -dp.receivedMessageCh:
msgType := msg.MessageType()
v, _ := dp.subscribersMap.Load(msgType)
if v == nil {
continue
? }
m, _ := v.(*sync.Map)
m.Range(func(key, valueinterface{}) bool {
select {
case key.(*Subscriber).msgChan - msg:
default:
logging.VLog().WithFields(logrus.Fields{
"msgType": msgType,
}).Warn("timeout to dispatch message.")
}
return true
? })
}
}
一個(gè)有點(diǎn)長(zhǎng)的循環(huán)
metricsDispatcherCached.Update(int64(len(dp.receivedMessageCh)))一秒鐘刷新一次緩沖區(qū)
case msg := -dp.receivedMessageCh:
msgType := msg.MessageType()如果能取出dp.receivedMessageCh
msgType := msg.MessageType()首先判斷取出的信息類型
v, _ := dp.subscribersMap.Load(msgType)
if v == nil {
continue
}
根據(jù)類型取出相應(yīng)的map
如果取不出,那么使用continue結(jié)束這個(gè)case
m, _ := v.(*sync.Map)
斷言
m.Range(func(key, valueinterface{}) bool {
select {
case key.(*Subscriber).msgChan - msg:
default:
logging.VLog().WithFields(logrus.Fields{
"msgType": msgType,
}).Warn("timeout to dispa+tch message.")
}
return true
})
將msg推入其他管道里面去。其他goruntime會(huì)循環(huán)等待該