GoCN每日新闻(2017-06-15)

回复

每日新闻astaxie 发起了问题 • 1 人关注 • 0 个回复 • 333 次浏览 • 2017-06-15 08:53 • 来自相关话题

【北京急聘】技术流互联网公司派派 诚招golang开发工程师及资深服务器开发

招聘应聘gomaster_me 发表了文章 • 0 个评论 • 452 次浏览 • 2017-06-14 23:55 • 来自相关话题

职位诱惑: B轮,IPO,扁平化管理,绩效奖金 职位描述:

工作职责:

  1. 参与产品基础服务平台的设计、研发工作,提升产品稳定性;

  2. 与产品经理尝试沟通产品需求;

    查看全部

职位诱惑:
B轮,IPO,扁平化管理,绩效奖金
职位描述:


工作职责:




  1. 参与产品基础服务平台的设计、研发工作,提升产品稳定性;




  2. 与产品经理尝试沟通产品需求;




  3. 进行相关产品的技术文档编写,方案设计;



  4. 学习研究业界先进技术,保持技术进步。


任职资格:




  1. 本科及以上学历,计算机相关专业,1年以上服务端研发经验;




  2. 深入理解计算机原理,有扎实的数据结构和算法基础;




  3. 深入理解linux系统及其原理,熟悉TCP/IP、HTTP协议以及网络编程;




  4. 良好的编码和文档习惯,对代码美感的追求孜孜不倦;




  5. 精通Go/C/C++/Python等至少一门语言,有Go开发经验者优先;




  6. 熟悉常用的sql、nosql数据库原理,阅读和理解优秀的开源系统代码;



  7. 具有分布式系统设计和开发经验者优先。


工作地点 北京 具体请发简历到邮箱(请注明来源 来自gocn.io) : gomaster_me@sina.com 我们将尽可能以最快的速度回复您。

golang实现基于redis和consul的可水平扩展的排行榜服务范例

文章分享changjixiong 发表了文章 • 1 个评论 • 198 次浏览 • 2017-06-14 22:15 • 来自相关话题

  本文的完整代码见https://github... 查看全部

  本文的完整代码见https://github.com/changjixion ... snotehttps://github.com/changjixiong/goNotes/tree/master/utilshttps://github.com/changjixion ... nvoke如果文中没有显示链接说明链接在被转发的时候被干掉了,请搜索找到原文阅读。


概述


  排行榜在各种互联网应用中广泛存在。本文将用一个范例说明如何利用redis和consul实现可水平扩展的等级排行榜服务。


redis的使用


  实现排行榜有2个地方需要用到redis:


  1.存储玩家的排行信息,这里使用的是Sorted Sets,代码如下


err := Rds.ZAdd(
PlayerLvRankKey,
redis.Z{
Score: lvScoreWithTime(playerInfo.Lv, time.Now().Unix()),
Member: playerInfo.PlayerID,
},
).Err()

  其中lvScoreWithTime根据玩家等级及到达的时间计算score用于排名,等级相同的情况下,先到达等级的计算分值大于后达到的。


  2.存储玩家自身的信息(名字,ID等),用于在排行榜中显示,毕竟仅仅只有排行的ID是不够的。这里采用hashset,代码如下


// ma的类型为map[string]string
err := Rds.HMSet(fmt.Sprintf("playerInfo:%d", playerID), ma).Err()

服务器端


  先初始化redis连接


rdsClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", "127.0.0.1", 6379),
Password: "123456",
DB: 0,
})
playercache.Rds = rdsClient
rankservice.Rds = rdsClient

  增加初始玩家信息(略)。


  注册服务器接口,此部分详细说明请参考《golang通过反射使用json字符串调用struct的指定方法及返回json结果》http://changjixiong.com/reflect-invoke-method-of-struct-and-get-json-format-result/


reflectinvoke.RegisterMethod(rankservice.DefaultRankService)

  将服务注册到consul,此部分详细说明请参考《golang使用服务发现系统consul》http://changjixiong.com/use-consul-in-golang/


go registerServer()

  在端口9528上开启服务用于结构client请求并返回结果


ln, err := net.Listen("tcp", "0.0.0.0:9528")

if nil != err {
panic("Error: " + err.Error())
}

for {
conn, err := ln.Accept()
// 对Accept()产生的临时错误的处理,可以参考net/http/server.go中的func (srv *Server) Serve(l net.Listener)
if err != nil {
panic("Error: " + err.Error())
}

go RankServer(conn)
}

  增加玩家经验及设置玩家的排行榜数据的接口如下


func (rankService *RankService) AddPlayerExp(playerID, exp int) bool {

player := playercache.GetPlayerInfo(playerID)
if nil == player {
return false
}

player.Exp += exp
// 固定经验升级,可以按需要修改
if player.Exp >= playercache.LvUpExp {
player.Lv += 1
player.Exp = player.Exp - playercache.LvUpExp
rankService.SetPlayerLvRank(player)
}

playercache.SetPlayerInfo(player)

return true
}

func (rankService *RankService) SetPlayerLvRank(playerInfo *playercache.PlayerInfo) bool {

if nil == playerInfo {
return false
}

err := Rds.ZAdd(
PlayerLvRankKey,
redis.Z{
Score: lvScoreWithTime(playerInfo.Lv, time.Now().Unix()),
Member: playerInfo.PlayerID,
},
).Err()

if nil != err {
log.Println("RankService: SetPlayerLvRank:", err)
return false
}

return true
}

  获取指定排行的玩家信息的接口


func (rankService *RankService) GetPlayerByLvRank(start, count int64) []*playercache.PlayerInfo {

playerInfos := []*playercache.PlayerInfo{}

ids, err := Rds.ZRevRange(PlayerLvRankKey, start, start+count-1).Result()

if nil != err {
log.Println("RankService: GetPlayerByLvRank:", err)
return playerInfos
}

for _, idstr := range ids {
id, err := strconv.Atoi(idstr)

if nil != err {
log.Println("RankService: GetPlayerByLvRank:", err)
} else {
playerInfo := playercache.LoadPlayerInfo(id)

if nil != playerInfos {
playerInfos = append(playerInfos, playerInfo)
}
}
}

return playerInfos

}

客户端


  连接到consul并查到到排行榜服务的地址,连接并发送请求


func main() {

client, err := consulapi.NewClient(consulapi.DefaultConfig())

if err != nil {
log.Fatal("consul client error : ", err)
}

for {

time.Sleep(time.Second * 3)
var services map[string]*consulapi.AgentService
var err error

services, err = client.Agent().Services()

log.Println("services", strings.Repeat("-", 80))
for _, service := range services {
log.Println(service)
}

if nil != err {
log.Println("in consual list Services:", err)
continue
}

if _, found := services["rankNode_1"]; !found {
log.Println("rankNode_1 not found")
continue
}
log.Println("choose", strings.Repeat("-", 80))
log.Println("rankNode_1", services["rankNode_1"])
sendData(services["rankNode_1"])

}
}

运行情况


  consul上注册了2个自定义的服务,一个是名为serverNode的echo服务(来源 《golang使用服务发现系统consul》),另一个是本文的排行榜服务rankNode。


  服务器接收到的请求片段


get: {"func_name":"AddPlayerExp","params":[4,41]}
get: {"func_name":"AddPlayerExp","params":[2,35]}
get: {"func_name":"AddPlayerExp","params":[5,27]}
get: {"func_name":"GetPlayerByLvRank","params":[0,3]}

  客户端在consul中查找到服务并连接rankNode_1


services ----------------------------------------------------------
&{consul consul [] 8300 false}
&{rankNode_1 rankNode [serverNode] 9528 127.0.0.1 false}
&{serverNode_1 serverNode [serverNode] 9527 127.0.0.1 false}
choose ------------------------------------------------------------
rankNode_1 &{rankNode_1 rankNode [serverNode] 9528 127.0.0.1 false}

  客户端收到的回应片段


get: {"func_name":"AddPlayerExp","data":[true],"errorcode":0}
get: {"func_name":"AddPlayerExp","data":[true],"errorcode":0}
get: {"func_name":"AddPlayerExp","data":[true],"errorcode":0}
get: {"func_name":"GetPlayerByLvRank","data":[[{"player_id":3,"player_name":"玩家3","exp":57,"lv":4,"online":true},{"player_id":2,"player_name":"玩家2","exp":31,"lv":4,"online":true},{"player_id":1,"player_name":"玩家1","exp":69,"lv":3,"online":true}]],"errorcode":0}

一点说明


  为什么说是可水平扩展的排行榜服务呢?文中已经看到,目前有2个自定的服务注册在consul上,client选择了rankNode_1,那么如果注册了多个rankNode,则可以在其中某些节点不可用时,client可以选择其他可用的节点获取服务,而当不可用的节点重新可用时,可以继续注册到consul以提供服务。

Golang 基础学习之Go map操作

GolangWilliamSheng 发表了文章 • 2 个评论 • 164 次浏览 • 2017-06-14 22:05 • 来自相关话题

package main

import "fmt"

func main() {
var countryMap map[string]string

/* 创建集合 */
cou... 			查看全部
					
package main

import "fmt"

func main() {
var countryMap map[string]string

/* 创建集合 */
countryMap = make(map[string]string)

/* map 插入 key-value */
countryMap["ShengRI"] = "1988-04-09"

/* 使用 key 输出 map 值 */
for country := range countryMap {
fmt.Println("Capital of",country,"is",countryMap[country])
}

/* 查看元素在集合中是否存在 */
captial, ok := countryMap["ShengRI"]
/* 如果 ok 是 true, 则存在,否则不存在 */
if(ok){
fmt.Println("Capital of United States is", captial)
}else {
fmt.Println("is not ok")
}

MyMap()

}

func MyMap(){
var myMap map[string]string
myMap = make(map[string]string)

myMap["idc_id"] = "2"
myMap["idc_name"] = "BeiJingIDC"
myMap["idc_prod"] = "OpenStack"
myMap["idc_zone"] = "BJ"
myMap["idc_abs"] = "2018-10-02"

for m := range myMap{
fmt.Println(m,myMap[m])
}

delete(myMap,"idc_abs")
fmt.Println(myMap)
myMap["idc_abs"] = "2088-10-02"

fmt.Println(myMap)

_, ok := myMap["idc_zone"]
if ok {
fmt.Println(myMap["idc_zone"],"is ok")
}

}

wechat_pusher : 基于Golang开发的微信消息定时推送框架

开源程序HundredLee 发表了文章 • 2 个评论 • 217 次浏览 • 2017-06-14 12:55 • 来自相关话题

wechat_pusher


Github



  • https://github.com/hundredlee/wechat_pusher

  • 欢迎star && fork && watch

  • 学Golang不久,写一个开源练练手。希望大家提提建议。谢谢

    功能列表


  • 消息推送

    • 模板消息推送

      • model -> message.go

      • task -> template_task.go


    • 图片推送(TODO)

    • 文字推送(TODO)

    • 图文推送(TODO)


  • 日志存储

  • 计划任务


如何开始?


第一步:当然是go get




  • go get github.com/hundredlee/wechat_pusher.git



  • 项目结构如下:


├── README.md
├── config
│   └── config.go
├── config.conf
├── config.conf.example
├── enum
│   └── task_type.go
├── glide.lock
├── glide.yaml
├── hlog
│   ├── filelog.go
│   ├── filelog_test.go
│   └── hlog.go
├── main.go
├── main.go.example
├── models
│   ├── message.go
│   └── token.go
├── redis
│   ├── redis.go
│   └── redis_test.go
├── statics
│   └── global.go
├── task
│   ├── task.go
│   └── template_task.go
├── utils
│   ├── access_token.go
│   ├── crontab.go
│   └── push.go
└── vendor
└── github.com

第二步:创建一个项目


创建配置文件



  • 项目根目录有一个config.conf.example,重命名为config.conf即可

  • 内容如下:


[WeChat]
APPID=
SECRET=
TOKEN=

[Redis]
POOL_SIZE=
TIMEOUT=
HOST=
PASS=
DB=

[Log]
LOG_PATH=


  • WeChat部分

    • APPID && SECRET && TOKEN 这些是微信开发者必须了解的东西。不细讲


  • Redis部分

    • POOL_SIZE 连接池大小 ,整型 int

    • TIMEOUT 连接超时时间 ,整型 int

    • HOST 连接的IP 字符串 string

    • PASS 密码 字符串 string

    • DB 数据库选择 整型 int



  • Log部分



    • LOG_PATH 日志存放文件夹,例如值为wechat_log,那么完整的目录应该是 GOPATH/wechat_log



  • 调用的时候这么写:



conf := config.Instance()
//例如wechat 的 appid
appId := conf.ConMap["WeChat.APPID"]

模板怎么配置



  • 以模板消息作为例子说明:

  • message.go 是模板消息的结构

  • template_task.go 是将一个模板消息封装成任务(template_task.go 是实现了接口task.go的)


mess := models.Message{
ToUser: "openid",
TemplateId: "templateid",
Url: "url",
Data: models.Data{
First: models.Raw{"xxx", "#173177"},
Subject: models.Raw{"xxx", "#173177"},
Sender: models.Raw{"xxx", "#173177"},
Remark: models.Raw{"xxx", "#173177"}}}

//封装成一个任务,TemplateTask表示模板消息任务
task := task.TemplateTask{}
task.SetTask(mess)


  • 以上代码是模板消息的配置,这个微信开发者应该都能看懂。


如何创建一个任务



  • 例如我们要创建一个模板消息定时推送任务

    • 第一步,封装任务

    • 第二步,添加任务,并设置任务类型、并发执行的个数、失败尝试次数等。

    • 第三步,启动任务


  • 我们用示例代码演示整个完整的过程


package main

import (
"github.com/hundredlee/wechat_pusher/enum"
"github.com/hundredlee/wechat_pusher/models"
"github.com/hundredlee/wechat_pusher/task"
"github.com/hundredlee/wechat_pusher/utils"
"runtime"
)

func main() {

runtime.GOMAXPROCS(runtime.NumCPU())
var tasks []task.Task
tasks = make([]task.Task, 100)
mess := models.Message{
ToUser: "oBv9cuLU5zyI27CtzI4VhV6Xabms",
TemplateId: "UXb6s5dahNC5Zt-xQIxbLJG1BdP8mP73LGLhNXl68J8",
Url: "http://baidu.com",
Data: models.Data{
First: models.Raw{"xxx", "#173177"},
Subject: models.Raw{"xxx", "#173177"},
Sender: models.Raw{"xxx", "#173177"},
Remark: models.Raw{"xxx", "#173177"}}}
task := task.TemplateTask{}
task.SetTask(mess)

for i := 0; i < 100; i++ {
tasks[i] = &task
}

utils.NewPush(tasks).SetTaskType(enum.TASK_TYPE_TEMPLATE).SetRetries(4).SetBufferNum(10).Add("45 * * * * *")
utils.StartCron()

}


Run



  • 很简单,当你组装好所有的task以后,直接运行一句话就可以了。


  • utils.NewPush(tasks).SetTaskType(enum.TASK_TYPE_TEMPLATE).SetRetries(4).SetBufferNum(10).Add("45 * * * * *")



  • utils.StartCron()


Contributor


GoCN每日新闻(2017-06-14)

回复

文章分享astaxie 发起了问题 • 1 人关注 • 0 个回复 • 312 次浏览 • 2017-06-14 10:58 • 来自相关话题

[上海]招募Golang工程师

招聘应聘photo 回复了问题 • 3 人关注 • 5 个回复 • 800 次浏览 • 2017-06-13 17:24 • 来自相关话题

golang 循环中的闭包问题

有问必答changwenlong 回复了问题 • 6 人关注 • 6 个回复 • 332 次浏览 • 2017-06-13 14:39 • 来自相关话题

[上海]中通快递 招聘 Golang 开发工程师 (12~40k)

回复

招聘应聘u0x01 发起了问题 • 1 人关注 • 0 个回复 • 495 次浏览 • 2017-06-13 12:05 • 来自相关话题

LiteIDE X32 发布,Go 语言开发工具

开源程序visualfc 发表了文章 • 2 个评论 • 251 次浏览 • 2017-06-13 11:44 • 来自相关话题

Go 语言开发工具 LiteIDE X32 正式发布。

历经三个月,200 多次源码提交,LiteIDE终于完成了新版本的发布,liteide.org 网站在 查看全部

Go 语言开发工具 LiteIDE X32 正式发布。


历经三个月,200 多次源码提交,LiteIDE终于完成了新版本的发布,liteide.org 网站在 HopeHook 的帮助下也正式推出。


LiteIDE X32 在界面会话、编译系统、源码编辑、代码分析等方面有了很大改进,从去年开始重写的 MulitFolderModel 也终于完成合并到 LiteIDE 的目录窗口中。



  • 提供了更多的界面主题和编辑器配色,感谢 HopeHook

  • 支持外部图标加载功能

  • 支持会话切换功能(会话保持自己的目录和文件)

  • 编译目录支持自定义 GOPATH

  • 编译目录支持更多的设置

  • 调试插件/Go编辑插件支持编译目录的 BUILDFLAGS -tags 设定

  • 完善 Go 代码导航和重构功能

  • 更多的功能更新和 BUG 修复见历史记录




更新记录 2017.6.12 Ver X32



  • LiteIDE

    • support folder build config custom GOPATH

    • support folder build config BUILDFLAGS -tags setup

    • support folder build config TARGETBASENAME setup

    • support session switching for folder/editor

    • support load custom icon library from liteapp/qrc folder (default and folder)

    • reimplemented multifolder model, it took me a long time :)

    • add macOS session menu for native dock menu

    • recent menu sync for multi windows

    • gotools support +build source navigate (single file or -tags setup)


  • LiteApp

    • add the session switching function

    • add autosavedocument emit message option

    • add max editor tab count option

    • add option action to standard toolbar

    • add tool window use shortcuts option for unstandard keyboard option

    • add exit liteide ctrl+q on windows

    • add themes (carbon.qss gray.qss sublime.qss) for liteide & beautify old themes, thanks for hope hook

    • editor tab context add open terminal here action

    • folders context menu add open in new windows action (new folder session)

    • folder view add show showdetails action

    • fix folder sync editor incorrect on macOS

    • fix webview and debug console qss

    • fix folders tool window enter key to jump

    • fix exit error save session by ctrl+q on macos

    • fix newfile dialog space name

    • update folder tool window showInExporer showInShell action text


  • LiteFind

    • find files add auto swith current folder checkbox

    • find in editor add show replace mode checkbox

    • filesearch enable replace whitespace or empty

    • editor replace all in one edit block for ctrl+z once undo


  • LiteBuild

    • add custom GOPATH in build config for build/debug/GolangEdit

    • add custom share-value BUILDFLAGS in build config for build/debug/GolangEdit

    • add custom TARGETBASENAME in build config for build/debug

    • support BUILDFLAGS -tags for build/debug/GolangEdit

    • update gosrc.xml to export custom value and share-value

    • folders tool window context menu add Go build configuration action

    • folders tool window context go tool use Go build configuration setup

    • fix stop action for kill process


  • LiteDebug

    • console use editor color scheme

    • support LiteBuild folder build config BUILDFLAGS/BUILDARGS -tags flag setup


  • DlvDebugger

    • fix process identify for auto exit


  • LiteEnv

    • default env /usr/local/go on macosx

    • update macosx cross env GOROOT for system


  • LiteEditor

    • context menu add convert case menu

    • go.snippet add iferr

    • update sublime.xml / sublime-bold.xml, thanks for hopehook hopehook@qq.com">hopehook@qq.com

    • alt+backspace delete serial whitespaces

    • option font QComboBox to QFontComboBox, add restore DefaultFont action

    • option add show monospace font check

    • option file types sort mimetype, show custom extsition first


  • GolangPackage

    • gopath setup add use sysgopath/litegopath check


  • GolangPlay

    • fix goplay use goenvironment


  • GolangDoc

    • change golang api index search for go/api folder


  • GolangEdit

    • add go root source readonly setup option

    • support folder go build config BUILDFLAGS/BUILDARGS -tags flag setup

    • fix interface type by gotools

    • fix find process stop and run

    • fix lookup guru for source query


  • GolangAst

    • fix astview enter key to jump


  • FileBorwser

    • fix file system enter key to jump


  • gotools

    • fix types interface method

    • types support +build for single source

    • types support -tags flag


  • tools

    • add new exportqrc tool for export liteide all build-in images


GoCN每日新闻(2017-06-13)

文章分享stirlingx 回复了问题 • 2 人关注 • 1 个回复 • 320 次浏览 • 2017-06-13 11:18 • 来自相关话题

教程go template代码不能运行的问题

有问必答silenceshell 回复了问题 • 2 人关注 • 1 个回复 • 222 次浏览 • 2017-06-13 10:56 • 来自相关话题

golang的gc消耗的cpu是系统态还是用户态?

有问必答plain 回复了问题 • 3 人关注 • 2 个回复 • 239 次浏览 • 2017-06-13 10:28 • 来自相关话题

Grab北京研发中心招聘

招聘应聘linjiawe 发表了文章 • 1 个评论 • 437 次浏览 • 2017-06-12 17:38 • 来自相关话题

Grab北京团队首次大型招募:寻找志同道合的你一起前行

Grab是东南亚最大的一站式多元化出行平台,Grab在新加坡,马来西亚,印尼,泰国,越南,菲律宾,缅甸7个国家40多个城市为近4千万用户提供出租车,私家车,顺风车和摩托车等全面出行服务... 查看全部

Grab北京团队首次大型招募:寻找志同道合的你一起前行


Grab是东南亚最大的一站式多元化出行平台,Grab在新加坡,马来西亚,印尼,泰国,越南,菲律宾,缅甸7个国家40多个城市为近4千万用户提供出租车,私家车,顺风车和摩托车等全面出行服务。去年9月Grab刚刚完成新一轮7.5亿美金的融资。


有人常问如何让招聘更吸引,有人回答有钱谈钱,没钱就谈理想。
在这里Grab想说,钱和理想我们都可以谈!


你是否忘了为什么来到北京?或者不知道该去向何处?还记得当初苦练“代码大全”和“程序设计语言”心法时留下的誓言吗?如果你依然怀揣梦想,冀望释放自己的创造力并真正发挥你的能力,而且愿意和你志同道合的人团队合作,加入我们这个年轻,激情,发展空间无限的团队吧,我们一起前行!


什么样的人更适合这个团队?


当你看到Grab的产品,发现它与你心目中的产品理念不谋而合,并认定它能够变得更好。最最重要的是感觉这件事“值得一做”而且认定只能是由你去完成。
那么没有错,你正是我们在寻找的那些注定是要加入这项事业并为之奋斗的人!下面是本次招聘的职位:


**前端(Web全栈),后端(Golang,无需有Golang经验),移动端(安卓,iOS)工程师


Full-stack Engineer / Backend Engineer / Mobile Engineer**


"把卓越的创新思想变成极致的产品体验,在我的世界里,我就是王"


与产品经理、商业运营经理、用户体验经理、数据运营经理等团队成员共同协作,深入理解业务需求,并提出相应的技术解决方案;
参与前端、后段及移动端技术架构,编写技术文档,参加技术评审活动;
能够从可靠性,可扩展性,可复用性,可维护性等多个角度进行技术架构设计;
与团队成员协作,编写代码并参与代码评审,按时交付符合质量要求的技术成果;
与项目管理团队协作,完成项目计划,并按计划推动项目实施;
参与前端、后端、移动端的运行维护工作,及时响应故障报警和用户反馈,快速处置问题,深刻检讨问题;
与整体技术团队所使用的技术栈和工具链保持一致,并能主动引入更好的工具以提升内部效率;
积极分享自己所做的产品或学习到的新技术,帮助建立团队的学习氛围;


**质量工程师


QA Engineer****


"6σ,我追求的不是星辰大海,而是错误率低于百万分之3.4"


按照产品架构和业务要求,制定和推进测试策略,测试计划和测试用例;
执行项目测试,包括分配测试资源,构建测试环境,编写测试代码,执行功能测试,集成测试,回归测试等;
通过测试相关流程、策略、方法和工具等创新,提升测试的质量和效率;
解决测试过程中的技术问题;


**地理系统工程师


GEO Engineer**


"老司机上路带你飞,开车这事儿你得听我的"


负责设计和实现核心路线规划引擎的工程架构;
开发和优化各类地理相关服务接口,提供高效稳定的服务;
利用机器学习算法,不断提升导航和导航估时(ETA)准确性;
负责地图及交通基础数据存储及更新的流程优化与模块化拆分;
研究新技术,掌握并实践业界前沿路线规划算法;
团队合作,代码评审,参与设计智能地理服务;



**技术经理


Engineer Manager**


"I know a Magic, Make Things Happen and Get Things Done"


Hands-on编程能力,架构设计能力,有快速学习、运用新技术的能力和意愿;
6年技术管理经验,有开发B2C产品、服务经验的优先;
有快速设计、实施、运维互联网服务的能力;
具备团队领导力,人际交往能力,能够推动项目实施;
具备沟通高层战略思想和底层技术实现细节的能力,尤其在跨领域,跨地域,跨组织,以及面向高级管理层的沟通;
很强的执行力;具备在一个动态变化的环境中平衡诸多事务的能力,能够抓住最关键问题;
对构筑完美的用户体验有执著的热情;


以上职位均要求英语沟通能力,否则我们如何拯救世界拯救歪果仁。


申请邮箱:benyuan.shi@grab.com
申请邮件命名主题:申请职位+姓名
邮件正文为求职信(说明意愿及优势),附件为简历
或直接访问网址在线申请:https://grab.careers/locations-china/


最后的话:
人生面临许多的选择,也许你不知道结果,但是你一定知道,这次旅程注定不一样,因为这次你并不孤单,Grab愿陪你一起成长。
Do not let the world limit you or let you limit yourself, join us today!

beego访问redis

技术讨论yuyifeichina 回复了问题 • 2 人关注 • 3 个回复 • 270 次浏览 • 2017-06-12 16:10 • 来自相关话题