從零到一:用Golang編寫(xiě)機(jī)器人


從一個(gè)有趣的項(xiàng)目來(lái)入門(mén)新的語(yǔ)言,再合適不過(guò)了雪隧。

本人也是通過(guò)編寫(xiě)一個(gè)可以聊天这溅,可以設(shè)置備忘/定時(shí)提醒,可以搜索美劇/電影資源等等功能的小機(jī)器人,迅速掌握了Go這門(mén)語(yǔ)言并喜歡上它讯柔。

文末會(huì)給出小機(jī)器人源碼及文中實(shí)例代碼鏈接抡蛙。

1. 先定個(gè)小目標(biāo)——從對(duì)話(huà)開(kāi)始

讓機(jī)器人“開(kāi)口說(shuō)話(huà)”是首要的,這里先采用第三方服務(wù)提供的API魂迄,本地通過(guò)HTTP請(qǐng)求獲取回答并返回粗截。

此階段基本沒(méi)有難點(diǎn),以Go為例捣炬,關(guān)鍵部分?jǐn)?shù)十行代碼解決:

//get reply from tlAI
func tlAI(info string) string {
    tuLingURL := fmt.Sprintf("http://www.tuling123.com/openapi/api?key=%s&info=%s", tlKey, url.QueryEscape(info))
    resp, err := http.Get(tuLingURL)
    if err != nil {
        log.Println(err)
        return ""
    }
    defer resp.Body.Close()
    reply := new(tlReply)
    decoder := json.NewDecoder(resp.Body) //decode reply from response body
    decoder.Decode(reply)
    return reply.Text
}

type tlReply struct {
    code int
    Text string `json:"text"`
}

2. 獨(dú)樂(lè)不如眾樂(lè)——分享給好友

通過(guò)第一步熊昌,機(jī)器人已經(jīng)具備了基礎(chǔ)的對(duì)話(huà)功能,此時(shí)可以開(kāi)始拉上好友一起調(diào)戲了遥金。
雖然Go語(yǔ)言可以編譯出多個(gè)平臺(tái)的可執(zhí)行文件用來(lái)分享(包括但不限于Linux浴捆、Windows、Mac OS)稿械,但我們有許多更方便更優(yōu)雅的方式选泻。

2.1 微信公眾號(hào)

通過(guò)微信開(kāi)發(fā)者平臺(tái)注冊(cè)一個(gè)公眾號(hào),加上上述的一點(diǎn)點(diǎn)代碼便可讓其具備對(duì)話(huà)功能:

2.2 網(wǎng)頁(yè)分享

通過(guò)一些簡(jiǎn)單的前端技術(shù)美莫,可以讓對(duì)話(huà)更人性化:
在線演示地址 (瀏覽器給予權(quán)限的話(huà)可支持語(yǔ)音輸入)

此處前后端采用WebSocket來(lái)通信:

//used by web samaritan robot
func socketHandler(w http.ResponseWriter, r *http.Request) {
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Print("upgrade:", err)
        return
    }
    defer c.Close()
    for {
        mt, in, err := c.ReadMessage() // read from user input
        if err != nil {
            log.Println("read:", err)
            break
        }
        ret := tlAI(string(in)) // get reply from tl AI robot
        for i := range ret {
            c.WriteMessage(mt, []byte(ret[i]))
            time.Sleep(time.Second)
        }
        c.WriteMessage(mt, []byte(""))
    }
}

通過(guò)WebSocket的推送功能页眯,讓對(duì)話(huà)返回效果(分段、限速)變得可控厢呵。

3. 增加技能點(diǎn)

僅有對(duì)話(huà)功能窝撵,只能稱(chēng)為聊天機(jī)器人,所以開(kāi)始添加新的功能襟铭。
以簡(jiǎn)單的添加備忘為例:

// SaveMemo create a memo for user, saved in redis
// command '/memo'
func (rb *Robot) SaveMemo(update tgbotapi.Update, step int) (ret string) {
    user := update.Message.Chat.UserName
    tmpAction := userAction[user]
    switch step {
    case 0:
        tmpAction.ActionStep++
        userAction[user] = tmpAction
        ret = "Ok, what do you want to save?"
    case 1:
        defer delete(userAction, user)
        when := time.Now().Format("2006-1-02 15:04")
        memo := update.Message.Text
        go conn.CreateMemo(user, when, memo)
        ret = "Ok, type '/memos' to see all your memos"
    }
    return
}

交互模式下碌奉,先判斷用戶(hù)交互狀態(tài)來(lái)給出不同回復(fù)。
使用go conn.CreateMemo(user, when, memo)異步生成Redis記錄寒砖。:

// CreateMemo saves a memo
func CreateMemo(user, when, memo string) {
    c := Pool.Get()
    defer c.Close()
    var setMemoLua = `
    local id = redis.call("INCR", "memoIncrId")
    redis.call("RPUSH", KEYS[1]..":memos", id)
    redis.call("HMSET", "memo:"..id, "time", KEYS[2], "content", KEYS[3])
    `
    script := redis.NewScript(3, setMemoLua)
    script.Do(c, user, when, memo)
}

4. 最后

至此赐劣,一個(gè)機(jī)器人的編寫(xiě)就結(jié)束了,從零到一創(chuàng)造出一個(gè)小機(jī)器人固然是有趣的哩都,而真正有趣的是從一到N的過(guò)程魁兼,腦洞有多大,小機(jī)器人的能力就有多大漠嵌。

文中代碼以及自己寫(xiě)的小機(jī)器人代碼鏈接: github/evolsnow/robot
如果有其他有趣的點(diǎn)子咐汞,歡迎一起來(lái)開(kāi)發(fā)玩耍。

補(bǔ)了一篇講解機(jī)器人自動(dòng)找資源的文章儒鹿,拋磚引玉之用~:一步一步教你的機(jī)器人尋找資源鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末化撕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挺身,更是在濱河造成了極大的恐慌侯谁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異墙贱,居然都是意外死亡热芹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)惨撇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伊脓,“玉大人,你說(shuō)我怎么就攤上這事魁衙”ㄇ唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵剖淀,是天一觀的道長(zhǎng)纯蛾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)纵隔,這世上最難降的妖魔是什么翻诉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮捌刮,結(jié)果婚禮上碰煌,老公的妹妹穿的比我還像新娘。我一直安慰自己绅作,他們只是感情好芦圾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著俄认,像睡著了一般个少。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眯杏,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天稍算,我揣著相機(jī)與錄音,去河邊找鬼役拴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛钾埂,可吹牛的內(nèi)容都是我干的河闰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼褥紫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姜性!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起髓考,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤部念,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體儡炼,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妓湘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乌询。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榜贴。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妹田,靈堂內(nèi)的尸體忽然破棺而出唬党,到底是詐尸還是另有隱情,我是刑警寧澤鬼佣,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布驶拱,位于F島的核電站,受9級(jí)特大地震影響晶衷,放射性物質(zhì)發(fā)生泄漏蓝纲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一房铭、第九天 我趴在偏房一處隱蔽的房頂上張望驻龟。 院中可真熱鬧,春花似錦缸匪、人聲如沸翁狐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至读宙,卻和暖如春砂心,著一層夾襖步出監(jiān)牢的瞬間懈词,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工辩诞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坎弯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓译暂,卻偏偏與公主長(zhǎng)得像抠忘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子外永,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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