善良的歹囝 發表於 2020-12-17 11:07:00

我是如何用go-zero 实现一个中台系统的

<p>最近发现golang社区里出了一个新星的微服务框架,来自好未来,光看这个名字,就很有奔头,之前,也只是玩过go-micro,其实真正的还没有在项目中运用过,只是觉得 微服务,grpc 这些很高大尚,还没有在项目中,真正的玩过,我看了一下官方提供的工具真的很好用,只需要定义好,舒适文件jia结构 都生成了,只需要关心业务,</p>
<p>加上最近 有个投票的活动,加上最近这几年中台也比较火,所以决定玩一下,</p>
<p>开源地址:&nbsp;https://github.com/jackluo2012/datacenter</p>
<p>先聊聊中台架构思路吧,look 先看架</p>
<p><img src="https://img2020.cnblogs.com/blog/203395/202012/203395-20201217094615171-335437652.jpg" alt="" loading="lazy"></p>
<p>中台的概念大概就是把一个一个的app 统一起来,反正我是这样理解的</p>
<p>先聊用户服务吧,现在一个公司有很多的公众号,小程序,微信的,支付宝的,还有xxx xxx ,很多的平台,每次开发的时候,我们总是需要做用户登陆的服务,不停的复制代码,然后我们就在思考能不能有一套独立的用户服务,</p>
<p>只需要告诉我你需要传个你要登陆的平台(比如微信),微信登陆,需要的是客户端返回给服务端一个code ,然后服务端拿着这个code去微信获取用户信息,反正大家都明白,</p>
<p>我们决定,将所有的信息 弄到 配置公共服务中去,里面在存,微信,支付宝,以及其它平台的 appid ,appkey,还有支付的appid,appkey,</p>
<p>这样就写一套</p>
<p>--------------------------------------------------------------------------------------------</p>
<p>go-zero:&nbsp; https://github.com/tal-tech/go-zero</p>
<p>最后说说实现吧,整个就一个repo&nbsp;</p>
<p>网关,我们用的是: go-zero的Api服务</p>
<p>其它它的是服务,我们就是用的go-zero的rpc服务</p>
<p>看下目录结构</p>
<p><img src="https://img2020.cnblogs.com/blog/203395/202012/203395-20201209110504600-317546535.png" alt="" loading="lazy"></p>
<p>整个项目完成,我一个人操刀, 写了1个来星期,我就实现了上面的中台系统;</p>
<p>go-zero作者私聊我说,可不可以写得丰富点,所以我决定把我的源码也加到文章里面</p>
<p>先看官方文档&nbsp;https://www.yuque.com/tal-tech/go-zero/yaoehb&nbsp;</p>
<p>我们先把网关搭建起来</p>
<div class="index-module_header_3qjZG">
<div class="index-module_title_1s0gC">
<h1 id="article-title" class="index-module_articleTitle_2xHPX">创建datacenter-api服务</h1>
</div>
</div>
<div class="index-module_content_Sqtvu">&nbsp;
<div class="cnblogs_code">
<p>➜ blogs mkdir datacenter &amp;&amp; cd datacenter<br>➜datacenter go mod init datacenter<br>go: creating new go.mod: module datacenter<br>➜datacenter</p>

</div>
<p>查看book目录</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">➜datacenter tree
.
└── go.mod

</span><span style="color: rgba(128, 0, 128, 1)">0</span> directories, <span style="color: rgba(128, 0, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">file</span></pre>
</div>
<h1 id="7810b09d" data-lake-id="aa3c525ab63107655acc306079f244a9" data-wording="true">二、创建api文件</h1>
<div class="cnblogs_code">
<pre>➜datacenter goctl api -<span style="color: rgba(0, 0, 0, 1)">o datacenter.api
Done.
➜datacenter tree
.
├── datacenter.api
└── go.mod</span></pre>
</div>
<h1 id="cb47c55d" data-lake-id="db478a1eb339dc266283e368832cb86c" data-wording="true">三、定义api服务 分别包含了上面的 公共服务,用户服务,和 投票活动服务</h1>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">info</span><span style="color: rgba(0, 0, 0, 1)">(
    title: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">中台系统</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO: add title</span>
    desc: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">中台系统</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO: add description</span>
    author: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">jackluo</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    email: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net.webjoy@gmail.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取 应用信息</span>
<span style="color: rgba(0, 0, 0, 1)">type Beid struct {
    Beid int64 `json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">beid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}
type Token struct{
    Token </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">token</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}
type WxTicket struct{
    Ticket </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ticket</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}
type Application struct {
    Sname </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Sname</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">名称</span>
    Logo <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">logo</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> login</span>
    Isclose int64 `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">isclose</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是否关闭</span>
    Fullwebsite <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">fullwebsite</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 全站名称</span>
<span style="color: rgba(0, 0, 0, 1)">}
type SnsReq struct{
    Beid
    Ptyid int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
    BackUrl <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">back_url</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">登陆返回的地址</span>
<span style="color: rgba(0, 0, 0, 1)">}
type SnsResp struct{
    Beid
    Ptyid int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
    Appid <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">appid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">sns 平台的id</span>
    Title <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">名称</span>
    LoginUrl <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">login_url</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">微信登陆的地址</span>
<span style="color: rgba(0, 0, 0, 1)">}

type WxShareResp struct {
    Appid </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">appid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Timestamp int64 `json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">timestamp</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Noncestr </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">noncestr</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Signature </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">signature</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}

@server(
    group: common
)
service datacenter</span>-<span style="color: rgba(0, 0, 0, 1)">api {
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">获取站点的信息</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler votesVerification
    get </span>/<span style="color: rgba(0, 0, 0, 1)">MP_verify_NT04cqknJe0em3mT.txt (SnsReq) returns (SnsResp)
   
    @handler appInfo
    get </span>/common/<span style="color: rgba(0, 0, 0, 1)">appinfo (Beid) returns (Application)
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">获取站点的社交属性信息</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler snsInfo
    post </span>/common/<span style="color: rgba(0, 0, 0, 1)">snsinfo (SnsReq) returns (SnsResp)
   
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取分享的</span>
<span style="color: rgba(0, 0, 0, 1)">    @handler wxTicket
    post </span>/common/wx/<span style="color: rgba(0, 0, 0, 1)">ticket (SnsReq) returns (WxShareResp)
   
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">上传需要登陆</span>
<span style="color: rgba(0, 0, 0, 1)">@server(
    jwt: Auth
    group: common
)
service datacenter</span>-<span style="color: rgba(0, 0, 0, 1)">api {
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">七牛上传凭证</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler qiuniuToken
    post </span>/common/qiuniu/<span style="color: rgba(0, 0, 0, 1)">token (Beid) returns (Token)
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">注册请求</span>
<span style="color: rgba(0, 0, 0, 1)">type RegisterReq struct {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO: add members here and delete this comment</span>
    Mobile   <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mobile</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">基本一个手机号码就完事</span>
    Password <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">password</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Smscode    </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">smscode</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">短信码</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">登陆请求</span>
<span style="color: rgba(0, 0, 0, 1)">type LoginReq struct{
    Mobile   </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mobile</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Type int64 `json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">type</span><span style="color: rgba(128, 0, 0, 1)">"</span>`    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1.密码登陆,2.短信登陆</span>
    Password <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">password</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">微信登陆</span>
<span style="color: rgba(0, 0, 0, 1)">type WxLoginReq struct {
    Beid      int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">beid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">应用id</span>
    Code <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">code</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">微信登陆密钥</span>
    Ptyid      int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
<span style="color: rgba(0, 0, 0, 1)">}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回用户信息</span>
<span style="color: rgba(0, 0, 0, 1)">type UserReply struct {
    Auid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">auid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Uid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">uid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Beid      int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">beid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">应用id</span>
    Ptyid      int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
    Username <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">username</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Mobile   </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mobile</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Nickname </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nickname</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Openid </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">openid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Avator </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">avator</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    JwtToken
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回APPUser</span>
<span style="color: rgba(0, 0, 0, 1)">type AppUser struct{
    Uid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">uid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Auid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">auid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Beid      int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">beid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">应用id</span>
    Ptyid      int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
    Nickname <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nickname</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Openid </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">openid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Avator </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">avator</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}

type LoginAppUser struct{
    Uid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">uid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Auid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">auid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Beid      int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">beid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">应用id</span>
    Ptyid      int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
    Nickname <span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nickname</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Openid </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">openid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Avator </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">avator</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    JwtToken
}

type JwtToken struct {
    AccessToken</span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">access_token,omitempty</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    AccessExpire int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">access_expire,omitempty</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    RefreshAfter int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">refresh_after,omitempty</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}

type UserReq struct{
    Auid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">auid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Uid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">uid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Beid      int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">beid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">应用id</span>
    Ptyid      int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ptyid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对应平台</span>
<span style="color: rgba(0, 0, 0, 1)">}

type Request {
    Name </span><span style="color: rgba(0, 0, 255, 1)">string</span> `path:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name,options=you|me</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}
type Response {
    Message </span><span style="color: rgba(0, 0, 255, 1)">string</span> `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">message</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
}

@server(
    group: user
)
service user</span>-<span style="color: rgba(0, 0, 0, 1)">api {
    @handler </span><span style="color: rgba(0, 0, 255, 1)">ping</span><span style="color: rgba(0, 0, 0, 1)">
    post </span>/user/<span style="color: rgba(0, 0, 255, 1)">ping</span><span style="color: rgba(0, 0, 0, 1)"> ()
   
    @handler register
    post </span>/user/<span style="color: rgba(0, 0, 0, 1)">register (RegisterReq) returns (UserReply)
   
    @handler </span><span style="color: rgba(0, 0, 255, 1)">login</span><span style="color: rgba(0, 0, 0, 1)">
    post </span>/user/<span style="color: rgba(0, 0, 255, 1)">login</span><span style="color: rgba(0, 0, 0, 1)"> (LoginReq) returns (UserReply)
   
    @handler wxlogin
    post </span>/user/wx/<span style="color: rgba(0, 0, 255, 1)">login</span><span style="color: rgba(0, 0, 0, 1)"> (WxLoginReq) returns (LoginAppUser)
   
    @handler code2Session
    get </span>/user/wx/<span style="color: rgba(0, 0, 255, 1)">login</span><span style="color: rgba(0, 0, 0, 1)"> () returns (LoginAppUser)
}
@server(
    jwt: Auth
    group: user
    middleware: Usercheck
)
service user</span>-<span style="color: rgba(0, 0, 0, 1)">api {
    @handler userInfo
    get </span>/user/dc/<span style="color: rgba(0, 0, 255, 1)">info</span><span style="color: rgba(0, 0, 0, 1)"> (UserReq) returns (UserReply)
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 投票活动api</span>
<span style="color: rgba(0, 0, 0, 1)">

type Actid struct {
    Actid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">actid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">活动id</span>
<span style="color: rgba(0, 0, 0, 1)">}

type VoteReq struct {
    Aeid       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">aeid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 作品id</span>
<span style="color: rgba(0, 0, 0, 1)">    Actid
}
type VoteResp struct {
    VoteReq
    Votecount       int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">votecount</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">投票票数</span>
    Viewcount       int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">viewcount</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">浏览数</span>
<span style="color: rgba(0, 0, 0, 1)">}


</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 活动返回的参数</span>
<span style="color: rgba(0, 0, 0, 1)">
type ActivityResp struct {
    Actid         int64`json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">actid</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">`
    Title         </span><span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">title</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">活动名称</span>
    Descr         <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">descr</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">活动描述</span>
    StartDate       int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">start_date</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">活动时间</span>
    EnrollDate      int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">enroll_date</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">投票时间</span>
    EndDate         int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">end_date</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">活动结束时间</span>
    Votecount       int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">votecount</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前活动的总票数</span>
    Viewcount       int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">viewcount</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前活动的总浏览数</span>
    Type            int64 `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">type</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">投票方式</span>
    Num                int64 `json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">num</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">投票几票</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">报名</span>
<span style="color: rgba(0, 0, 0, 1)">

type EnrollReq struct {
    Actid
    Name         </span><span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 名称</span>
    Address         <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">address</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">地址</span>
    Images         []<span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">作品图片</span>
    Descr         <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">descr</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 作品描述</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 作品返回</span>
<span style="color: rgba(0, 0, 0, 1)">
type EnrollResp struct {
    Actid
    Aeid      int64 `json:</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">aeid</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 作品id</span>
    Name         <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 名称</span>
    Address         <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">address</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">地址</span>
    Images         []<span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">images</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">作品图片</span>
    Descr         <span style="color: rgba(0, 0, 255, 1)">string</span>`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">descr</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 作品描述</span>
    Votecount       int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">votecount</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前活动的总票数</span>
    Viewcount       int64`json:<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">viewcount</span><span style="color: rgba(128, 0, 0, 1)">"</span>` <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当前活动的总浏览数</span>
<span style="color: rgba(0, 0, 0, 1)">   
}


@server(
    group: votes
)
service votes</span>-<span style="color: rgba(0, 0, 0, 1)">api {
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">获取活动的信息</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler activityInfo
    get </span>/votes/activity/<span style="color: rgba(0, 0, 255, 1)">info</span><span style="color: rgba(0, 0, 0, 1)"> (Actid) returns (ActivityResp)
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">活动访问+1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler activityIcrView
    get </span>/votes/activity/<span style="color: rgba(0, 0, 0, 1)">view (Actid) returns (ActivityResp)
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">获取报名的投票作品信息</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler enrollInfo
    get </span>/votes/enroll/<span style="color: rgba(0, 0, 255, 1)">info</span><span style="color: rgba(0, 0, 0, 1)"> (VoteReq) returns (EnrollResp)
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">获取报名的投票作品列表</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler enrollLists
    get </span>/votes/enroll/<span style="color: rgba(0, 0, 0, 1)">lists (Actid)    returns(EnrollResp)
}

@server(
    jwt: Auth
    group: votes
    middleware: Usercheck
)
service votes</span>-<span style="color: rgba(0, 0, 0, 1)">api {
    @doc(
      summary: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">投票</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    )
    @handler vote
    post </span>/votes/<span style="color: rgba(0, 0, 0, 1)">vote (VoteReq) returns (VoteResp)
    @handler enroll
    post </span>/votes/<span style="color: rgba(0, 0, 0, 1)">enroll (EnrollReq) returns (EnrollResp)
}</span></pre>
</div>
<p>上面基本上写就写的API及文档的思路</p>
<h1 id="c3018b1e" data-lake-id="54c204d65580d0385d68c4b3dc5040ef" data-wording="true">四、生成datacenter api服务</h1>
</div>
<div class="cnblogs_code">
<pre>➜datacenter goctl api go -api datacenter.api -<span style="color: rgba(0, 0, 255, 1)">dir</span><span style="color: rgba(0, 0, 0, 1)"> .
Done.
➜datacenter tree
.
├── datacenter.api
├── etc
│&nbsp;&nbsp; └── datacenter</span>-<span style="color: rgba(0, 0, 0, 1)">api.yaml
├── go.mod
├── internal
│&nbsp;&nbsp; ├── config
│&nbsp;&nbsp; │&nbsp;&nbsp; └── config.go
│&nbsp;&nbsp; ├── handler
│&nbsp;&nbsp; │&nbsp;&nbsp; ├── common
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── appinfohandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── qiuniutokenhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── snsinfohandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── votesverificationhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; └── wxtickethandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; ├── routes.go
│&nbsp;&nbsp; │&nbsp;&nbsp; ├── user
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── code2sessionhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── loginhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── pinghandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── registerhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── userinfohandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; └── wxloginhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp; └── votes
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── activityicrviewhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── activityinfohandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── enrollhandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── enrollinfohandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── enrolllistshandler.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   └── votehandler.go
│&nbsp;&nbsp; ├── logic
│&nbsp;&nbsp; │&nbsp;&nbsp; ├── common
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── appinfologic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── qiuniutokenlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── snsinfologic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── votesverificationlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; └── wxticketlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; ├── user
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── code2sessionlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── loginlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── pinglogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── registerlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; ├── userinfologic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; │&nbsp;&nbsp; └── wxloginlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp; └── votes
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── activityicrviewlogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── activityinfologic.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── enrollinfologic.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── enrolllistslogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   ├── enrolllogic.go
│&nbsp;&nbsp; │&nbsp;&nbsp;   └── votelogic.go
│&nbsp;&nbsp; ├── middleware
│&nbsp;&nbsp; │&nbsp;&nbsp; └── usercheckmiddleware.go
│&nbsp;&nbsp; ├── svc
│&nbsp;&nbsp; │&nbsp;&nbsp; └── servicecontext.go
│&nbsp;&nbsp; └── types
│&nbsp;&nbsp;   └── types.go
└── datacenter.go

</span><span style="color: rgba(128, 0, 128, 1)">14</span> directories, <span style="color: rgba(128, 0, 128, 1)">43</span> files</pre>
</div>
<p>我们打开etc/datacenter-api.yaml 把必要的配置信息加上</p>
<div class="cnblogs_code">
<pre>Name: datacenter-<span style="color: rgba(0, 0, 0, 1)">api
Log:
Mode: console
Host: </span><span style="color: rgba(128, 0, 128, 1)">0.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.0</span><span style="color: rgba(0, 0, 0, 1)">
Port: </span><span style="color: rgba(128, 0, 128, 1)">8857</span><span style="color: rgba(0, 0, 0, 1)">
Auth:
AccessSecret: 你的jwtwon Secret</span><span style="color: rgba(0, 0, 0, 1)">
AccessExpire: </span><span style="color: rgba(128, 0, 128, 1)">86400</span><span style="color: rgba(0, 0, 0, 1)">
CacheRedis:
</span>- Host: <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">6379</span><span style="color: rgba(0, 0, 0, 1)">
Pass: 密码
Type: node            </span><span style="color: rgba(0, 0, 0, 1)">         
UserRpc:
Etcd:
    Hosts:
      </span>- <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">2379</span><span style="color: rgba(0, 0, 0, 1)">
    Key: user.rpc
CommonRpc:
Etcd:
    Hosts:
      </span>- <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">2379</span><span style="color: rgba(0, 0, 0, 1)">
    Key: common.rpc
VotesRpc:
Etcd:
    Hosts:
      </span>- <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">2379</span><span style="color: rgba(0, 0, 0, 1)">
    Key: votes.rpc      </span></pre>
</div>
<p>上面的&nbsp;UserRpc,和&nbsp;CommonRpc ,还有VotesRpc 这些我先写上,后面再来慢慢加</p>
<p>我们先来写CommonRpc的服务</p>
<h3 id="Sn3vs" data-lake-id="153d30d45e77ae609fb8969f6fe40f93" data-wording="true">新建项目目录</h3>
<div class="cnblogs_code">
<pre>➜datacenter <span style="color: rgba(0, 0, 255, 1)">mkdir -p</span> common/rpc &amp;&amp; cd common/rpc</pre>
</div>
<p>直接就新建在了,datacenter目录中,因为common 里面,可能以后会不只会提供rpc服务,可能还有api的服务,所以又加了rpc目录</p>
<h3 id="QPKjm" data-lake-id="0a10b874431d9e912fb4ed156c8cda48" data-wording="true">goctl创建模板</h3>
<div class="cnblogs_code">
<pre>➜rpc goctl rpc template -o=<span style="color: rgba(0, 0, 0, 1)">common.proto
➜rpc </span><span style="color: rgba(0, 0, 255, 1)">ls</span><span style="color: rgba(0, 0, 0, 1)">
common.proto</span></pre>
</div>
<p>往里面填入内容</p>
<div class="cnblogs_code">
<pre>➜rpc <span style="color: rgba(0, 0, 255, 1)">cat</span> <span style="color: rgba(0, 0, 0, 1)">common.proto
syntax </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">proto3</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

package common;


message BaseAppReq{
int64 beid</span>=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
}

message BaseAppResp{
int64 beid</span>=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">string</span> logo=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">string</span> sname=<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
int64 isclose</span>=<span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">string</span> fullwebsite=<span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请求的api</span>
<span style="color: rgba(0, 0, 0, 1)">message AppConfigReq {
int64 beid</span>=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
int64 ptyid</span>=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回的值</span>
<span style="color: rgba(0, 0, 0, 1)">message AppConfigResp {
int64 </span><span style="color: rgba(0, 0, 255, 1)">id</span>=<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
int64 beid</span>=<span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">;
int64 ptyid</span>=<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">string</span> appid=<span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">string</span> appsecret=<span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">string</span> title=<span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">;
}

service Common {
rpc GetAppConfig(AppConfigReq) returns(AppConfigResp);
rpc GetBaseApp(BaseAppReq) returns(BaseAppResp);
}</span></pre>
</div>
<p>&nbsp;</p>
<h3 id="C4NRo" data-lake-id="32463a77db92c00b7ab12c0c451a32bc" data-wording="true">gotcl生成rpc服务</h3>
<div class="cnblogs_code">
<pre>➜rpc goctl rpc proto -src common.proto -<span style="color: rgba(0, 0, 255, 1)">dir</span><span style="color: rgba(0, 0, 0, 1)"> .
protoc</span>-I=/Users/jackluo/works/blogs/datacenter/common/rpc common.proto --go_out=plugins=grpc:/Users/jackluo/works/blogs/datacenter/common/rpc/<span style="color: rgba(0, 0, 0, 1)">common
Done.<br></span></pre>
<p>➜ rpc tree<br>.<br>├── common<br>│&nbsp;&nbsp; └── common.pb.go<br>├── common.go<br>├── common.proto<br>├── commonclient<br>│&nbsp;&nbsp; └── common.go<br>├── etc<br>│&nbsp;&nbsp; └── common.yaml<br>└── internal<br>    ├── config<br>    │&nbsp;&nbsp; └── config.go<br>    ├── logic<br>    │&nbsp;&nbsp; ├── getappconfiglogic.go<br>    │&nbsp;&nbsp; └── getbaseapplogic.go<br>    ├── server<br>    │&nbsp;&nbsp; └── commonserver.go<br>    └── svc<br>      └── servicecontext.go</p>
<pre></pre>
<p>8 directories, 10 files</p>
<pre><span style="color: rgba(0, 0, 0, 1)">&nbsp;</span></pre>
</div>
<p>基本上,就把所有的目录规范和结构的东西都生成了,就不用纠结项目目录了,怎么放了,怎么组织了</p>
<p>看一下,配置信息,里面可以写入mysql和其它redis的信息</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">Name: common.rpc
ListenOn: </span><span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">8081</span><span style="color: rgba(0, 0, 0, 1)">
Mysql:
DataSource: root:admin@tcp(</span><span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">3306</span>)/datacenter?charset=utf8&amp;parseTime=<span style="color: rgba(0, 0, 255, 1)">true</span>&amp;loc=Asia%<span style="color: rgba(0, 0, 0, 1)">2FShanghai
CacheRedis:
</span>- Host: <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">6379</span><span style="color: rgba(0, 0, 0, 1)">
Pass:
Type: node
Etcd:
Hosts:
</span>- <span style="color: rgba(128, 0, 128, 1)">127.0</span>.<span style="color: rgba(128, 0, 128, 1)">0.1</span>:<span style="color: rgba(128, 0, 128, 1)">2379</span><span style="color: rgba(0, 0, 0, 1)">
Key: common.rpc</span></pre>
</div>
<p>我们再来加上数据库的服务</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">➜rpc cd ..
➜common </span><span style="color: rgba(0, 0, 255, 1)">ls</span><span style="color: rgba(0, 0, 0, 1)">
rpc
➜common </span><span style="color: rgba(0, 0, 255, 1)">pwd</span>
/Users/jackluo/works/blogs/datacenter/<span style="color: rgba(0, 0, 0, 1)">common
➜common goctl model mysql datasource </span>-url=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">root:admin@tcp(127.0.0.1:3306)/datacenter</span><span style="color: rgba(128, 0, 0, 1)">"</span> -table=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">base_app</span><span style="color: rgba(128, 0, 0, 1)">"</span> -<span style="color: rgba(0, 0, 255, 1)">dir</span> ./model -<span style="color: rgba(0, 0, 0, 1)">c
Done.
➜common tree
.
├── model
│&nbsp;&nbsp; ├── baseappmodel.go
│&nbsp;&nbsp; └── vars.go
└── rpc
    ├── common
    │&nbsp;&nbsp; └── common.pb.go
    ├── common.go
    ├── common.proto
    ├── commonclient
    │&nbsp;&nbsp; └── common.go
    ├── etc
    │&nbsp;&nbsp; └── common.yaml
    └── internal
      ├── config
      │&nbsp;&nbsp; └── config.go
      ├── logic
      │&nbsp;&nbsp; ├── getappconfiglogic.go
      │&nbsp;&nbsp; └── getbaseapplogic.go
      ├── server
      │&nbsp;&nbsp; └── commonserver.go
      └── svc
            └── servicecontext.go

</span><span style="color: rgba(128, 0, 128, 1)">10</span> directories, <span style="color: rgba(128, 0, 128, 1)">12</span> files</pre>
</div>
<p>这样基本的一个rpc就写完了,然后我们将rpc 和model 还有api串连起来,这个官方的文档已经很详细了,这里就只是贴一下代码</p>
<div class="cnblogs_code">
<pre>➜common <span style="color: rgba(0, 0, 255, 1)">cat</span> rpc/internal/config/<span style="color: rgba(0, 0, 0, 1)">config.go
package config

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/stores/cache</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/zrpc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

type Config struct {
    zrpc.RpcServerConf
    Mysql struct {
      DataSource </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">
    }
    CacheRedis cache.ClusterConf
}</span></pre>
</div>
<p>再在svc中修改</p>
<div class="cnblogs_code">
<pre>➜common <span style="color: rgba(0, 0, 255, 1)">cat</span> rpc/internal/svc/<span style="color: rgba(0, 0, 0, 1)">servicecontext.go
package svc

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/common/model</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/common/rpc/internal/config</span><span style="color: rgba(128, 0, 0, 1)">"</span>

    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/stores/sqlx</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

type ServiceContext struct {
    c            config.Config
    AppConfigModel model.AppConfigModel
    BaseAppModel   model.BaseAppModel
}

func NewServiceContext(c config.Config) </span>*<span style="color: rgba(0, 0, 0, 1)">ServiceContext {
    conn :</span>=<span style="color: rgba(0, 0, 0, 1)"> sqlx.NewMysql(c.Mysql.DataSource)
    apm :</span>=<span style="color: rgba(0, 0, 0, 1)"> model.NewAppConfigModel(conn, c.CacheRedis)
    bam :</span>=<span style="color: rgba(0, 0, 0, 1)"> model.NewBaseAppModel(conn, c.CacheRedis)
    return </span>&amp;<span style="color: rgba(0, 0, 0, 1)">ServiceContext{
      c:            c,
      AppConfigModel: apm,
      BaseAppModel:   bam,
    }
}</span></pre>
</div>
<p>上面的代码已经将rpc 和 model 数据库关联起来了,我们现在再将rpc 和 api关联起来</p>
<div class="cnblogs_code">
<pre>➜datacenter <span style="color: rgba(0, 0, 255, 1)">cat</span> internal/config/<span style="color: rgba(0, 0, 0, 1)">config.go

package config

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/stores/cache</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/rest</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/zrpc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

type Config struct {
    rest.RestConf

    Auth struct {
      AccessSecret </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">
      AccessExpire int64
    }
    UserRpc   zrpc.RpcClientConf
    CommonRpc zrpc.RpcClientConf
    VotesRpczrpc.RpcClientConf

    CacheRedis cache.ClusterConf
}</span></pre>
</div>
<p>加入svc服务中</p>
<div class="cnblogs_code">
<pre>➜datacenter <span style="color: rgba(0, 0, 255, 1)">cat</span> internal/svc/<span style="color: rgba(0, 0, 0, 1)">servicecontext.go
package svc

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">context</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/common/rpc/commonclient</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/internal/config</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/internal/middleware</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/shared</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/user/rpc/userclient</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/votes/rpc/votesclient</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">fmt</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">net/http</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">time</span><span style="color: rgba(128, 0, 0, 1)">"</span>

    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/logx</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/stores/cache</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/stores/redis</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/syncx</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/rest</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/zrpc</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">google.golang.org/grpc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

type ServiceContext struct {
    Config         config.Config
    GreetMiddleware1 rest.Middleware
    GreetMiddleware2 rest.Middleware
    Usercheck      rest.Middleware
    UserRpc          userclient.User </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用户</span>
<span style="color: rgba(0, 0, 0, 1)">    CommonRpc      commonclient.Common
    VotesRpc         votesclient.Votes
    Cache            cache.Cache
    RedisConn      </span>*<span style="color: rgba(0, 0, 0, 1)">redis.Redis
}

func timeInterceptor(ctx context.Context, method </span><span style="color: rgba(0, 0, 255, 1)">string</span>, req, reply interface{}, <span style="color: rgba(0, 0, 255, 1)">cc</span> *<span style="color: rgba(0, 0, 0, 1)">grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
    stime :</span>= <span style="color: rgba(0, 0, 255, 1)">time</span><span style="color: rgba(0, 0, 0, 1)">.Now()
    err :</span>= invoker(ctx, method, req, reply, <span style="color: rgba(0, 0, 255, 1)">cc</span><span style="color: rgba(0, 0, 0, 1)">, opts...)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
      return err
    }

    </span><span style="color: rgba(0, 0, 255, 1)">fmt</span>.Printf(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">调用 %s 方法 耗时: %v\n</span><span style="color: rgba(128, 0, 0, 1)">"</span>, method, <span style="color: rgba(0, 0, 255, 1)">time</span><span style="color: rgba(0, 0, 0, 1)">.Now().Sub(stime))
    return nil
}
func NewServiceContext(c config.Config) </span>*<span style="color: rgba(0, 0, 0, 1)">ServiceContext {

    ur :</span>=<span style="color: rgba(0, 0, 0, 1)"> userclient.NewUser(zrpc.MustNewClient(c.UserRpc, zrpc.WithUnaryClientInterceptor(timeInterceptor)))
    cr :</span>=<span style="color: rgba(0, 0, 0, 1)"> commonclient.NewCommon(zrpc.MustNewClient(c.CommonRpc, zrpc.WithUnaryClientInterceptor(timeInterceptor)))
    vr :</span>=<span style="color: rgba(0, 0, 0, 1)"> votesclient.NewVotes(zrpc.MustNewClient(c.VotesRpc, zrpc.WithUnaryClientInterceptor(timeInterceptor)))
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">缓存</span>
    ca := cache.NewCache(c.CacheRedis, syncx.NewSharedCalls(), cache.NewCacheStat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">dc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">), shared.ErrNotFound)
    rcon :</span>= redis.NewRedis(c.CacheRedis[<span style="color: rgba(128, 0, 128, 1)">0</span>].Host, c.CacheRedis[<span style="color: rgba(128, 0, 128, 1)">0</span>].Type, c.CacheRedis[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">].Pass)
    return </span>&amp;<span style="color: rgba(0, 0, 0, 1)">ServiceContext{
      Config:         c,
      GreetMiddleware1: greetMiddleware1,
      GreetMiddleware2: greetMiddleware2,
      Usercheck:      middleware.NewUserCheckMiddleware().Handle,
      UserRpc:          ur,
      CommonRpc:      cr,
      VotesRpc:         vr,
      Cache:            ca,
      RedisConn:      rcon,
    }
}</span></pre>
</div>
<p>这样基本上,我们就可以在logic的文件目录中调用了</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">cat</span> internal/logic/common/<span style="color: rgba(0, 0, 0, 1)">appinfologic.go

package logic

import (
    </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">context</span><span style="color: rgba(128, 0, 0, 1)">"</span>

    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/internal/svc</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/internal/types</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/shared</span><span style="color: rgba(128, 0, 0, 1)">"</span>

    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/common/model</span><span style="color: rgba(128, 0, 0, 1)">"</span>
    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">datacenter/common/rpc/common</span><span style="color: rgba(128, 0, 0, 1)">"</span>

    <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">github.com/tal-tech/go-zero/core/logx</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
)

type AppInfoLogic struct {
    logx.Logger
    ctx    context.Context
    svcCtx </span>*<span style="color: rgba(0, 0, 0, 1)">svc.ServiceContext
}

func NewAppInfoLogic(ctx context.Context, svcCtx </span>*<span style="color: rgba(0, 0, 0, 1)">svc.ServiceContext) AppInfoLogic {
    return AppInfoLogic{
      Logger: logx.WithContext(ctx),
      ctx:    ctx,
      svcCtx: svcCtx,
    }
}

func (l </span>*AppInfoLogic) AppInfo(req types.Beid) (appconfig *<span style="color: rgba(0, 0, 0, 1)">common.BaseAppResp, err error) {

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查 缓存中是否有值</span>
    err =<span style="color: rgba(0, 0, 0, 1)"> l.svcCtx.Cache.GetCache(model.GetcacheBaseAppIdPrefix(req.Beid), appconfig)
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> err != nil &amp;&amp; err ==<span style="color: rgba(0, 0, 0, 1)"> shared.ErrNotFound {
      appconfig, err </span>= l.svcCtx.CommonRpc.GetBaseApp(l.ctx, &amp;<span style="color: rgba(0, 0, 0, 1)">common.BaseAppReq{
            Beid: req.Beid,
      })
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> err !=<span style="color: rgba(0, 0, 0, 1)"> nil {
            return
      }
      err </span>=<span style="color: rgba(0, 0, 0, 1)"> l.svcCtx.Cache.SetCache(model.GetcacheBaseAppIdPrefix(req.Beid), appconfig)
    }

    return
}</span></pre>
</div>
<p>这样,基本就连接起来了,其它基本上就不用改了,UserRPC,和VotesRPC类似,这里就不在写了</p>
<h1 id="a0cce463" data-lake-id="358a83899c466cbdbf17b7b06de39467" data-wording="true">下面我说说使用心得吧</h1>
<p>go-zero 的确香,因为它有一个goctl 的工具,他可以自动的把代码结构全部的生成好,我们就不再去纠结,目录结构 ,怎么组织,没有个好几年的架构能力是不好实现的,有什么规范那些,并发,熔断,完全不用,考滤其它的,专心的实现业务就好,像微服务,还要有服务发现,一系列的东西,都不用关心,因为go-zero内部已经实现了,我写代码也写了有10多年了,之前一直用的php,比较出名的就 laravel,thinkphp,基本上就是模块化的,像微服那些实现直来真的有成本,但是你用上go-zero,你就像调api接口一样简单的开发,其它什么服务发现,那些根本就不用关注了,只需要关注业务。一个好的语言,框架,他们的底层思维,永远都是效率高,不加班的思想,我相信go-zero会提高你和你团队或是公司的效率。go-zero的作者说,他们有个团队专门整理go-zero框架,目的也应该很明显,那就是提高,他们自己的开发效率,流程化,标准化,是提高工作效率的准则,像我们平时遇到了问题,或是遇到了bug,我第一个想到的不是怎么去解决我的bug,而是在想我的流程是不是有问题,我的哪个流程会导致bug,最后我相信go-zero 能成为 微服务开发 的首选框架</p>
<p>最后说说遇到的坑吧:</p>
<p>grpc 本人第一次用,然后就遇到了,有些字符为空时,字段值不显示的问题:</p>
<p>通过grpc官方库中的<code>jsonpb</code>来实现,官方在它的设定中有一个结构体用来实现<code>protoc buffer</code>转换为JSON结构,并可以根据字段来配置转换的要求</p>
<p>跨域问题:</p>
<p>go-zero的设置了,感觉没有效果,大佬说通过nginx 设置,后面发现还是不行,最近 ,强行弄到了一个域名下,后面有时间再解决</p>
<p>go-zero的sqlx 问题,这个真的费了很长的时间,</p>
<div class="cnblogs_code">
<pre>time.Time 这个数据结构,数据库中用的是 timestamp 这个 比如我的字段 是delete_at 默认数库设置的是null ,结果插入的时候,<br>就报了Incorrect datetime value: '0000-00-00' for column 'deleted_at' at row 1"}这个错,<br>查询的时候报deleted_at\": unsupported Scan, storing driver.Value type \u003cnil\u003e into type *time.Time" <br>后面果断去掉了这个字段<br>字段上面加上 .omitempty 这个标签,好像也有用,`db:".omitempty"`</pre>
</div>
<p>其次就是这个&nbsp;&nbsp;Conversion from collation utf8_general_ci into utf8mb4_unicode_ci,这个导致的大概原因是,现在都喜欢用emj表情了,mysql数据识别不了</p>
<p>最后发现是数据连接问题:</p>
<p>mysql这边照样按照原始的方式,将配置文件修改编码格式<br>重新创建数据库,并且设置数据库编码为utf8mb4 ,排序规则为utf8mb4_unicode_ci<br>(这样的话,所有的表还有string字段都是这个编码格式,如果不想所有的都是,可以单独设置,这个不是重点.因为在navicat上都好设置,手动点一下就行了)<br>重点来了:golang中使用的是 github.com/go-sql-driver/mysql驱动,<br>将连接mysql的dsn:(因为我这使用的是gorm,所以dsn可能跟原生的格式不太一样,不过没关系,只需要关注charset和collation就行了)<br>root:password@/name?parseTime=True&amp;loc=Local&amp;charset=utf8<br>修改为:<br>root:password@/name?parseTime=True&amp;loc=Local&amp;charset=utf8mb4&amp;collation=utf8mb4_unicode_ci</p>
<p>---------------------------------</p>
<p>mark</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/jackluo/p/14148518.html
頁: [1]
查看完整版本: 我是如何用go-zero 实现一个中台系统的