[{"data":1,"prerenderedAt":1389},["ShallowReactive",2],{"content:\u002F2025\u002F12\u002Fgrpc-4method":3,"surround:\u002F2025\u002F12\u002Fgrpc-4method":1378},{"id":4,"title":5,"body":6,"categories":1355,"date":1357,"description":1358,"draft":1359,"extension":1360,"image":1361,"meta":1362,"navigation":831,"path":1364,"permalink":1361,"published":1361,"readingTime":1365,"recommend":1361,"references":1361,"seo":1370,"sitemap":1371,"stem":1372,"tags":1373,"type":1375,"updated":1376,"__hash__":1377},"content\u002Fposts\u002F2025\u002F12\u002Fgrpc-4method.md","gRPC 四种通信模式详解",{"type":7,"value":8,"toc":1345},"minimark",[9,13,17,25,29,46,51,57,61,66,73,235,240,457,461,466,470,590,594,791,795,800,804,1083,1087,1332,1335,1341],[10,11,12],"p",{},"本文主要介绍 gRPC 的四种调用方式。",[14,15,16],"h2",{"id":16},"官方教程",[10,18,19],{},[20,21,22],"a",{"href":22,"rel":23},"https:\u002F\u002Fgrpc.io\u002Fdocs\u002Flanguages\u002Fgo\u002Fbasics\u002F",[24],"nofollow",[14,26,28],{"id":27},"grpc-的四种调用方式","gRPC 的四种调用方式",[10,30,31,32,36,37,36,40,36,43],{},"分为四部分：",[33,34,35],"code",{"code":35},"Unary RPC","、",[33,38,39],{"code":39},"Client Streaming",[33,41,42],{"code":42},"Server Streaming",[33,44,45],{"code":45},"Bidirectional Streaming",[47,48,50],"h3",{"id":49},"_1-unary-rpc","1. Unary RPC",[52,53,54],"blockquote",{},[10,55,56],{},"客户端发送单个请求，服务器返回单个响应，类似http请求，此处代码略过...",[47,58,60],{"id":59},"_2-client-streaming","2. Client Streaming",[52,62,63],{},[10,64,65],{},"客户端发送多条消息，服务器接收所有消息后返回一个聚合响应",[10,67,68,72],{},[69,70,71],"strong",{},"客户端示例",":",[74,75,80],"pre",{"className":76,"code":77,"language":78,"meta":79,"style":79},"language-go shiki shiki-themes github-light github-dark","userStream, _ := aiClient.ChatWithUserStream(ctx)\nwords := []string{\"how\", \"are\", \"you\"}\nfor _, word := range words {\n    userStream.Send(&pb.ChatMsg{Msg: word})\n}\nuserStreamReply, _ := userStream.CloseAndRecv()\n","go","",[33,81,82,112,153,173,212,217],{"__ignoreMap":79},[83,84,87,91,95,98,102,106,109],"span",{"class":85,"data-line":86,"line":86},"line",1,[83,88,90],{"class":89},"sVt8B","userStream, _ ",[83,92,94],{"class":93},"szBVR",":=",[83,96,97],{"class":89}," aiClient.",[83,99,101],{"class":100},"sScJk","ChatWithUserStream",[83,103,105],{"class":104},"sSDpw","(",[83,107,108],{"class":89},"ctx",[83,110,111],{"class":104},")\n",[83,113,115,118,120,123,126,129,132,135,139,142,145,147,150],{"class":85,"data-line":114,"line":114},2,[83,116,117],{"class":89},"words ",[83,119,94],{"class":93},[83,121,122],{"class":89}," ",[83,124,125],{"class":104},"[",[83,127,128],{"class":104},"]",[83,130,131],{"class":93},"string",[83,133,134],{"class":104},"{",[83,136,138],{"class":137},"sZZnC","\"how\"",[83,140,141],{"class":89},", ",[83,143,144],{"class":137},"\"are\"",[83,146,141],{"class":89},[83,148,149],{"class":137},"\"you\"",[83,151,152],{"class":104},"}\n",[83,154,156,159,162,164,167,170],{"class":85,"data-line":155,"line":155},3,[83,157,158],{"class":93},"for",[83,160,161],{"class":89}," _, word ",[83,163,94],{"class":93},[83,165,166],{"class":93}," range",[83,168,169],{"class":89}," words ",[83,171,172],{"class":104},"{\n",[83,174,176,180,183,186,189,192,195,198,201,204,207,210],{"class":85,"data-line":175,"line":175},4,[83,177,179],{"class":178},"indent","    ",[83,181,182],{"class":89},"userStream.",[83,184,185],{"class":100},"Send",[83,187,105],{"class":188},"sJX2D",[83,190,191],{"class":93},"&",[83,193,194],{"class":100},"pb",[83,196,197],{"class":89},".",[83,199,200],{"class":100},"ChatMsg",[83,202,134],{"class":203},"sqkie",[83,205,206],{"class":89},"Msg: word",[83,208,209],{"class":203},"}",[83,211,111],{"class":188},[83,213,215],{"class":85,"data-line":214,"line":214},5,[83,216,152],{"class":104},[83,218,220,223,225,228,231,233],{"class":85,"data-line":219,"line":219},6,[83,221,222],{"class":89},"userStreamReply, _ ",[83,224,94],{"class":93},[83,226,227],{"class":89}," userStream.",[83,229,230],{"class":100},"CloseAndRecv",[83,232,105],{"class":104},[83,234,111],{"class":104},[10,236,237,72],{},[69,238,239],{},"服务端示例",[74,241,243],{"className":76,"code":242,"language":78,"meta":79,"style":79},"func (s *AIService) ChatWithUserStream(stream grpc.ClientStreamingServer[pb.ChatMsg, pb.ChatMsg]) error {\n    respMsg := \"\"\n    for {\n        chatReq, err := stream.Recv()\n        if err == io.EOF {\n            return stream.SendAndClose(&pb.ChatMsg{Msg: respMsg})\n        }\n        respMsg = respMsg + chatReq.Msg\n    }\n}\n",[33,244,245,313,325,335,356,376,411,422,443,452],{"__ignoreMap":79},[83,246,247,250,252,254,258,261,264,267,269,271,273,276,279,281,284,286,288,290,292,294,296,298,300,302,304,306,309,311],{"class":85,"data-line":86,"line":86},[83,248,249],{"class":93},"func",[83,251,122],{"class":89},[83,253,105],{"class":104},[83,255,257],{"class":256},"s4XuR","s ",[83,259,260],{"class":93},"*",[83,262,263],{"class":100},"AIService",[83,265,266],{"class":104},")",[83,268,122],{"class":89},[83,270,101],{"class":100},[83,272,105],{"class":104},[83,274,275],{"class":256},"stream",[83,277,278],{"class":100}," grpc",[83,280,197],{"class":89},[83,282,283],{"class":100},"ClientStreamingServer",[83,285,125],{"class":188},[83,287,194],{"class":100},[83,289,197],{"class":89},[83,291,200],{"class":100},[83,293,141],{"class":89},[83,295,194],{"class":100},[83,297,197],{"class":89},[83,299,200],{"class":100},[83,301,128],{"class":188},[83,303,266],{"class":104},[83,305,122],{"class":89},[83,307,308],{"class":93},"error",[83,310,122],{"class":89},[83,312,172],{"class":104},[83,314,315,317,320,322],{"class":85,"data-line":114,"line":114},[83,316,179],{"class":178},[83,318,319],{"class":89},"respMsg ",[83,321,94],{"class":93},[83,323,324],{"class":137}," \"\"\n",[83,326,327,329,331,333],{"class":85,"data-line":155,"line":155},[83,328,179],{"class":178},[83,330,158],{"class":93},[83,332,122],{"class":89},[83,334,172],{"class":188},[83,336,337,339,341,344,346,349,352,354],{"class":85,"data-line":175,"line":175},[83,338,179],{"class":178},[83,340,179],{"class":178},[83,342,343],{"class":89},"chatReq, err ",[83,345,94],{"class":93},[83,347,348],{"class":89}," stream.",[83,350,351],{"class":100},"Recv",[83,353,105],{"class":203},[83,355,111],{"class":203},[83,357,358,360,362,365,368,371,374],{"class":85,"data-line":214,"line":214},[83,359,179],{"class":178},[83,361,179],{"class":178},[83,363,364],{"class":93},"if",[83,366,367],{"class":89}," err ",[83,369,370],{"class":93},"==",[83,372,373],{"class":89}," io.EOF ",[83,375,172],{"class":203},[83,377,378,380,382,384,387,389,392,394,396,398,400,402,404,407,409],{"class":85,"data-line":219,"line":219},[83,379,179],{"class":178},[83,381,179],{"class":178},[83,383,179],{"class":178},[83,385,386],{"class":93},"return",[83,388,348],{"class":89},[83,390,391],{"class":100},"SendAndClose",[83,393,105],{"class":104},[83,395,191],{"class":93},[83,397,194],{"class":100},[83,399,197],{"class":89},[83,401,200],{"class":100},[83,403,134],{"class":188},[83,405,406],{"class":89},"Msg: respMsg",[83,408,209],{"class":188},[83,410,111],{"class":104},[83,412,414,416,418,420],{"class":85,"data-line":413,"line":413},7,[83,415,179],{"class":178},[83,417,179],{"class":178},[83,419,79],{"class":89},[83,421,152],{"class":203},[83,423,425,427,429,431,434,437,440],{"class":85,"data-line":424,"line":424},8,[83,426,179],{"class":178},[83,428,179],{"class":178},[83,430,319],{"class":89},[83,432,433],{"class":93},"=",[83,435,436],{"class":89}," respMsg ",[83,438,439],{"class":93},"+",[83,441,442],{"class":89}," chatReq.Msg\n",[83,444,446,448,450],{"class":85,"data-line":445,"line":445},9,[83,447,179],{"class":178},[83,449,79],{"class":89},[83,451,152],{"class":188},[83,453,455],{"class":85,"data-line":454,"line":454},10,[83,456,152],{"class":104},[47,458,460],{"id":459},"_3-server-streaming","3. Server Streaming",[52,462,463],{},[10,464,465],{},"客户端发送单个请求，服务器返回多条消息流",[10,467,468,72],{},[69,469,71],{},[74,471,473],{"className":76,"code":472,"language":78,"meta":79,"style":79},"aiStream, _ := aiClient.ChatWithAIStream(ctx, &pb.ChatMsg{Msg: \"hello,I want to ask a question\"})\nfor {\n    aiStreamReply, err := aiStream.Recv()\n    if err == io.EOF {\n        break\n    }\n    log.Println(aiStreamReply.Msg)\n}\n",[33,474,475,512,520,538,552,561,569,586],{"__ignoreMap":79},[83,476,477,480,482,484,487,489,492,494,496,498,500,502,505,508,510],{"class":85,"data-line":86,"line":86},[83,478,479],{"class":89},"aiStream, _ ",[83,481,94],{"class":93},[83,483,97],{"class":89},[83,485,486],{"class":100},"ChatWithAIStream",[83,488,105],{"class":104},[83,490,491],{"class":89},"ctx, ",[83,493,191],{"class":93},[83,495,194],{"class":100},[83,497,197],{"class":89},[83,499,200],{"class":100},[83,501,134],{"class":188},[83,503,504],{"class":89},"Msg: ",[83,506,507],{"class":137},"\"hello,I want to ask a question\"",[83,509,209],{"class":188},[83,511,111],{"class":104},[83,513,514,516,518],{"class":85,"data-line":114,"line":114},[83,515,158],{"class":93},[83,517,122],{"class":89},[83,519,172],{"class":104},[83,521,522,524,527,529,532,534,536],{"class":85,"data-line":155,"line":155},[83,523,179],{"class":178},[83,525,526],{"class":89},"aiStreamReply, err ",[83,528,94],{"class":93},[83,530,531],{"class":89}," aiStream.",[83,533,351],{"class":100},[83,535,105],{"class":188},[83,537,111],{"class":188},[83,539,540,542,544,546,548,550],{"class":85,"data-line":175,"line":175},[83,541,179],{"class":178},[83,543,364],{"class":93},[83,545,367],{"class":89},[83,547,370],{"class":93},[83,549,373],{"class":89},[83,551,172],{"class":188},[83,553,554,556,558],{"class":85,"data-line":214,"line":214},[83,555,179],{"class":178},[83,557,179],{"class":178},[83,559,560],{"class":93},"break\n",[83,562,563,565,567],{"class":85,"data-line":219,"line":219},[83,564,179],{"class":178},[83,566,79],{"class":89},[83,568,152],{"class":188},[83,570,571,573,576,579,581,584],{"class":85,"data-line":413,"line":413},[83,572,179],{"class":178},[83,574,575],{"class":89},"log.",[83,577,578],{"class":100},"Println",[83,580,105],{"class":188},[83,582,583],{"class":89},"aiStreamReply.Msg",[83,585,111],{"class":188},[83,587,588],{"class":85,"data-line":424,"line":424},[83,589,152],{"class":104},[10,591,592,72],{},[69,593,239],{},[74,595,597],{"className":76,"code":596,"language":78,"meta":79,"style":79},"func (s *AIService) ChatWithAIStream(in *pb.ChatMsg, stream grpc.ServerStreamingServer[pb.ChatMsg]) error {\n    stream.Send(&pb.ChatMsg{Msg: in.Msg})\n    words := []string{\"wait\", \"a\", \"minute\"}\n    for _, word := range words {\n        stream.Send(&pb.ChatMsg{Msg: word})\n    }\n    return nil\n}\n",[33,598,599,664,692,725,741,769,777,787],{"__ignoreMap":79},[83,600,601,603,605,607,609,611,613,615,617,619,621,624,627,629,631,633,635,637,639,641,644,646,648,650,652,654,656,658,660,662],{"class":85,"data-line":86,"line":86},[83,602,249],{"class":93},[83,604,122],{"class":89},[83,606,105],{"class":104},[83,608,257],{"class":256},[83,610,260],{"class":93},[83,612,263],{"class":100},[83,614,266],{"class":104},[83,616,122],{"class":89},[83,618,486],{"class":100},[83,620,105],{"class":104},[83,622,623],{"class":256},"in",[83,625,626],{"class":93}," *",[83,628,194],{"class":100},[83,630,197],{"class":89},[83,632,200],{"class":100},[83,634,141],{"class":89},[83,636,275],{"class":256},[83,638,278],{"class":100},[83,640,197],{"class":89},[83,642,643],{"class":100},"ServerStreamingServer",[83,645,125],{"class":188},[83,647,194],{"class":100},[83,649,197],{"class":89},[83,651,200],{"class":100},[83,653,128],{"class":188},[83,655,266],{"class":104},[83,657,122],{"class":89},[83,659,308],{"class":93},[83,661,122],{"class":89},[83,663,172],{"class":104},[83,665,666,668,671,673,675,677,679,681,683,685,688,690],{"class":85,"data-line":114,"line":114},[83,667,179],{"class":178},[83,669,670],{"class":89},"stream.",[83,672,185],{"class":100},[83,674,105],{"class":188},[83,676,191],{"class":93},[83,678,194],{"class":100},[83,680,197],{"class":89},[83,682,200],{"class":100},[83,684,134],{"class":203},[83,686,687],{"class":89},"Msg: in.Msg",[83,689,209],{"class":203},[83,691,111],{"class":188},[83,693,694,696,698,700,702,704,706,708,710,713,715,718,720,723],{"class":85,"data-line":155,"line":155},[83,695,179],{"class":178},[83,697,117],{"class":89},[83,699,94],{"class":93},[83,701,122],{"class":89},[83,703,125],{"class":188},[83,705,128],{"class":188},[83,707,131],{"class":93},[83,709,134],{"class":188},[83,711,712],{"class":137},"\"wait\"",[83,714,141],{"class":89},[83,716,717],{"class":137},"\"a\"",[83,719,141],{"class":89},[83,721,722],{"class":137},"\"minute\"",[83,724,152],{"class":188},[83,726,727,729,731,733,735,737,739],{"class":85,"data-line":175,"line":175},[83,728,179],{"class":178},[83,730,158],{"class":93},[83,732,161],{"class":89},[83,734,94],{"class":93},[83,736,166],{"class":93},[83,738,169],{"class":89},[83,740,172],{"class":188},[83,742,743,745,747,749,751,753,755,757,759,761,763,765,767],{"class":85,"data-line":214,"line":214},[83,744,179],{"class":178},[83,746,179],{"class":178},[83,748,670],{"class":89},[83,750,185],{"class":100},[83,752,105],{"class":203},[83,754,191],{"class":93},[83,756,194],{"class":100},[83,758,197],{"class":89},[83,760,200],{"class":100},[83,762,134],{"class":104},[83,764,206],{"class":89},[83,766,209],{"class":104},[83,768,111],{"class":203},[83,770,771,773,775],{"class":85,"data-line":219,"line":219},[83,772,179],{"class":178},[83,774,79],{"class":89},[83,776,152],{"class":188},[83,778,779,781,783],{"class":85,"data-line":413,"line":413},[83,780,179],{"class":178},[83,782,386],{"class":93},[83,784,786],{"class":785},"sj4cs"," nil\n",[83,788,789],{"class":85,"data-line":424,"line":424},[83,790,152],{"class":104},[47,792,794],{"id":793},"_4-bidirectional-streaming","4. Bidirectional Streaming",[52,796,797],{},[10,798,799],{},"客户端和服务器都可以随时发送消息，类似于实时聊天",[10,801,802,72],{},[69,803,71],{},[74,805,807],{"className":76,"code":806,"language":78,"meta":79,"style":79},"userAIStream, _ := aiClient.ChatWithUserAIStream(ctx)\n\n\u002F\u002F 启动 goroutine 接收服务器消息\ngo func() {\n    for {\n        userAIStreamReply, err := userAIStream.Recv()\n        if err != nil {\n            log.Fatalf(\"failed to get userAIStreamReply,err:%v\", err)\n        }\n        log.Println(userAIStreamReply.Msg)\n    }\n}()\n\n\u002F\u002F 从标准输入读取并发送消息\nfor {\n    reader := bufio.NewReader(os.Stdin)\n    line, _ := reader.ReadString('\\n')\n    userAIStream.Send(&pb.ChatMsg{Msg: line})\n}\n",[33,808,809,827,833,839,854,864,884,904,933,943,960,969,978,983,989,998,1021,1049,1078],{"__ignoreMap":79},[83,810,811,814,816,818,821,823,825],{"class":85,"data-line":86,"line":86},[83,812,813],{"class":89},"userAIStream, _ ",[83,815,94],{"class":93},[83,817,97],{"class":89},[83,819,820],{"class":100},"ChatWithUserAIStream",[83,822,105],{"class":104},[83,824,108],{"class":89},[83,826,111],{"class":104},[83,828,829],{"class":85,"data-line":114,"line":114},[83,830,832],{"emptyLinePlaceholder":831},true,"\n",[83,834,835],{"class":85,"data-line":155,"line":155},[83,836,838],{"class":837},"sJ8bj","\u002F\u002F 启动 goroutine 接收服务器消息\n",[83,840,841,843,846,848,850,852],{"class":85,"data-line":175,"line":175},[83,842,78],{"class":93},[83,844,845],{"class":93}," func",[83,847,105],{"class":104},[83,849,266],{"class":104},[83,851,122],{"class":89},[83,853,172],{"class":104},[83,855,856,858,860,862],{"class":85,"data-line":214,"line":214},[83,857,179],{"class":178},[83,859,158],{"class":93},[83,861,122],{"class":89},[83,863,172],{"class":188},[83,865,866,868,870,873,875,878,880,882],{"class":85,"data-line":219,"line":219},[83,867,179],{"class":178},[83,869,179],{"class":178},[83,871,872],{"class":89},"userAIStreamReply, err ",[83,874,94],{"class":93},[83,876,877],{"class":89}," userAIStream.",[83,879,351],{"class":100},[83,881,105],{"class":203},[83,883,111],{"class":203},[83,885,886,888,890,892,894,897,900,902],{"class":85,"data-line":413,"line":413},[83,887,179],{"class":178},[83,889,179],{"class":178},[83,891,364],{"class":93},[83,893,367],{"class":89},[83,895,896],{"class":93},"!=",[83,898,899],{"class":785}," nil",[83,901,122],{"class":89},[83,903,172],{"class":203},[83,905,906,908,910,912,914,917,919,922,925,928,931],{"class":85,"data-line":424,"line":424},[83,907,179],{"class":178},[83,909,179],{"class":178},[83,911,179],{"class":178},[83,913,575],{"class":89},[83,915,916],{"class":100},"Fatalf",[83,918,105],{"class":104},[83,920,921],{"class":137},"\"failed to get userAIStreamReply,err:",[83,923,924],{"class":785},"%v",[83,926,927],{"class":137},"\"",[83,929,930],{"class":89},", err",[83,932,111],{"class":104},[83,934,935,937,939,941],{"class":85,"data-line":445,"line":445},[83,936,179],{"class":178},[83,938,179],{"class":178},[83,940,79],{"class":89},[83,942,152],{"class":203},[83,944,945,947,949,951,953,955,958],{"class":85,"data-line":454,"line":454},[83,946,179],{"class":178},[83,948,179],{"class":178},[83,950,575],{"class":89},[83,952,578],{"class":100},[83,954,105],{"class":203},[83,956,957],{"class":89},"userAIStreamReply.Msg",[83,959,111],{"class":203},[83,961,963,965,967],{"class":85,"data-line":962,"line":962},11,[83,964,179],{"class":178},[83,966,79],{"class":89},[83,968,152],{"class":188},[83,970,972,974,976],{"class":85,"data-line":971,"line":971},12,[83,973,209],{"class":104},[83,975,105],{"class":104},[83,977,111],{"class":104},[83,979,981],{"class":85,"data-line":980,"line":980},13,[83,982,832],{"emptyLinePlaceholder":831},[83,984,986],{"class":85,"data-line":985,"line":985},14,[83,987,988],{"class":837},"\u002F\u002F 从标准输入读取并发送消息\n",[83,990,992,994,996],{"class":85,"data-line":991,"line":991},15,[83,993,158],{"class":93},[83,995,122],{"class":89},[83,997,172],{"class":104},[83,999,1001,1003,1006,1008,1011,1014,1016,1019],{"class":85,"data-line":1000,"line":1000},16,[83,1002,179],{"class":178},[83,1004,1005],{"class":89},"reader ",[83,1007,94],{"class":93},[83,1009,1010],{"class":89}," bufio.",[83,1012,1013],{"class":100},"NewReader",[83,1015,105],{"class":188},[83,1017,1018],{"class":89},"os.Stdin",[83,1020,111],{"class":188},[83,1022,1024,1026,1029,1031,1034,1037,1039,1042,1045,1047],{"class":85,"data-line":1023,"line":1023},17,[83,1025,179],{"class":178},[83,1027,1028],{"class":89},"line, _ ",[83,1030,94],{"class":93},[83,1032,1033],{"class":89}," reader.",[83,1035,1036],{"class":100},"ReadString",[83,1038,105],{"class":188},[83,1040,1041],{"class":137},"'",[83,1043,1044],{"class":785},"\\n",[83,1046,1041],{"class":137},[83,1048,111],{"class":188},[83,1050,1052,1054,1057,1059,1061,1063,1065,1067,1069,1071,1074,1076],{"class":85,"data-line":1051,"line":1051},18,[83,1053,179],{"class":178},[83,1055,1056],{"class":89},"userAIStream.",[83,1058,185],{"class":100},[83,1060,105],{"class":188},[83,1062,191],{"class":93},[83,1064,194],{"class":100},[83,1066,197],{"class":89},[83,1068,200],{"class":100},[83,1070,134],{"class":203},[83,1072,1073],{"class":89},"Msg: line",[83,1075,209],{"class":203},[83,1077,111],{"class":188},[83,1079,1081],{"class":85,"data-line":1080,"line":1080},19,[83,1082,152],{"class":104},[10,1084,1085,72],{},[69,1086,239],{},[74,1088,1090],{"className":76,"code":1089,"language":78,"meta":79,"style":79},"func (s *AIService) ChatWithUserAIStream(stream grpc.BidiStreamingServer[pb.ChatMsg, pb.ChatMsg]) error {\n    for {\n        chatReq, err := stream.Recv()\n        if err == io.EOF {\n            break\n        }\n        if err != nil {\n            return err\n        }\n        replyMsg := replace(chatReq.Msg)  \u002F\u002F 文本转换\n        stream.Send(&pb.ChatMsg{Msg: replyMsg})\n    }\n    return nil\n}\n",[33,1091,1092,1151,1161,1179,1195,1205,1215,1233,1246,1256,1283,1312,1320,1328],{"__ignoreMap":79},[83,1093,1094,1096,1098,1100,1102,1104,1106,1108,1110,1112,1114,1116,1118,1120,1123,1125,1127,1129,1131,1133,1135,1137,1139,1141,1143,1145,1147,1149],{"class":85,"data-line":86,"line":86},[83,1095,249],{"class":93},[83,1097,122],{"class":89},[83,1099,105],{"class":104},[83,1101,257],{"class":256},[83,1103,260],{"class":93},[83,1105,263],{"class":100},[83,1107,266],{"class":104},[83,1109,122],{"class":89},[83,1111,820],{"class":100},[83,1113,105],{"class":104},[83,1115,275],{"class":256},[83,1117,278],{"class":100},[83,1119,197],{"class":89},[83,1121,1122],{"class":100},"BidiStreamingServer",[83,1124,125],{"class":188},[83,1126,194],{"class":100},[83,1128,197],{"class":89},[83,1130,200],{"class":100},[83,1132,141],{"class":89},[83,1134,194],{"class":100},[83,1136,197],{"class":89},[83,1138,200],{"class":100},[83,1140,128],{"class":188},[83,1142,266],{"class":104},[83,1144,122],{"class":89},[83,1146,308],{"class":93},[83,1148,122],{"class":89},[83,1150,172],{"class":104},[83,1152,1153,1155,1157,1159],{"class":85,"data-line":114,"line":114},[83,1154,179],{"class":178},[83,1156,158],{"class":93},[83,1158,122],{"class":89},[83,1160,172],{"class":188},[83,1162,1163,1165,1167,1169,1171,1173,1175,1177],{"class":85,"data-line":155,"line":155},[83,1164,179],{"class":178},[83,1166,179],{"class":178},[83,1168,343],{"class":89},[83,1170,94],{"class":93},[83,1172,348],{"class":89},[83,1174,351],{"class":100},[83,1176,105],{"class":203},[83,1178,111],{"class":203},[83,1180,1181,1183,1185,1187,1189,1191,1193],{"class":85,"data-line":175,"line":175},[83,1182,179],{"class":178},[83,1184,179],{"class":178},[83,1186,364],{"class":93},[83,1188,367],{"class":89},[83,1190,370],{"class":93},[83,1192,373],{"class":89},[83,1194,172],{"class":203},[83,1196,1197,1199,1201,1203],{"class":85,"data-line":214,"line":214},[83,1198,179],{"class":178},[83,1200,179],{"class":178},[83,1202,179],{"class":178},[83,1204,560],{"class":93},[83,1206,1207,1209,1211,1213],{"class":85,"data-line":219,"line":219},[83,1208,179],{"class":178},[83,1210,179],{"class":178},[83,1212,79],{"class":89},[83,1214,152],{"class":203},[83,1216,1217,1219,1221,1223,1225,1227,1229,1231],{"class":85,"data-line":413,"line":413},[83,1218,179],{"class":178},[83,1220,179],{"class":178},[83,1222,364],{"class":93},[83,1224,367],{"class":89},[83,1226,896],{"class":93},[83,1228,899],{"class":785},[83,1230,122],{"class":89},[83,1232,172],{"class":203},[83,1234,1235,1237,1239,1241,1243],{"class":85,"data-line":424,"line":424},[83,1236,179],{"class":178},[83,1238,179],{"class":178},[83,1240,179],{"class":178},[83,1242,386],{"class":93},[83,1244,1245],{"class":89}," err\n",[83,1247,1248,1250,1252,1254],{"class":85,"data-line":445,"line":445},[83,1249,179],{"class":178},[83,1251,179],{"class":178},[83,1253,79],{"class":89},[83,1255,152],{"class":203},[83,1257,1258,1260,1262,1265,1267,1270,1272,1275,1277,1280],{"class":85,"data-line":454,"line":454},[83,1259,179],{"class":178},[83,1261,179],{"class":178},[83,1263,1264],{"class":89},"replyMsg ",[83,1266,94],{"class":93},[83,1268,1269],{"class":100}," replace",[83,1271,105],{"class":203},[83,1273,1274],{"class":89},"chatReq.Msg",[83,1276,266],{"class":203},[83,1278,1279],{"class":89},"  ",[83,1281,1282],{"class":837},"\u002F\u002F 文本转换\n",[83,1284,1285,1287,1289,1291,1293,1295,1297,1299,1301,1303,1305,1308,1310],{"class":85,"data-line":962,"line":962},[83,1286,179],{"class":178},[83,1288,179],{"class":178},[83,1290,670],{"class":89},[83,1292,185],{"class":100},[83,1294,105],{"class":203},[83,1296,191],{"class":93},[83,1298,194],{"class":100},[83,1300,197],{"class":89},[83,1302,200],{"class":100},[83,1304,134],{"class":104},[83,1306,1307],{"class":89},"Msg: replyMsg",[83,1309,209],{"class":104},[83,1311,111],{"class":203},[83,1313,1314,1316,1318],{"class":85,"data-line":971,"line":971},[83,1315,179],{"class":178},[83,1317,79],{"class":89},[83,1319,152],{"class":188},[83,1321,1322,1324,1326],{"class":85,"data-line":980,"line":980},[83,1323,179],{"class":178},[83,1325,386],{"class":93},[83,1327,786],{"class":785},[83,1329,1330],{"class":85,"data-line":985,"line":985},[83,1331,152],{"class":104},[14,1333,1334],{"id":1334},"后端代码地址",[10,1336,1337],{},[20,1338,1339],{"href":1339,"rel":1340},"https:\u002F\u002Fcnb.cool\u002Fcodepzj\u002Fgoplayground\u002F-\u002Ftree\u002Fmain\u002Frpc-learn\u002Fgrpc-4method",[24],[1342,1343,1344],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sSDpw, html code.shiki .sSDpw{--shiki-default:#005cc5;--shiki-dark:#79b8ff}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJX2D, html code.shiki .sJX2D{--shiki-default:#e36209;--shiki-dark:#ffab70}html pre.shiki code .sqkie, html code.shiki .sqkie{--shiki-default:#5a32a3;--shiki-dark:#b392f0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":79,"searchDepth":175,"depth":175,"links":1346},[1347,1348,1354],{"id":16,"depth":114,"text":16},{"id":27,"depth":114,"text":28,"children":1349},[1350,1351,1352,1353],{"id":49,"depth":155,"text":50},{"id":59,"depth":155,"text":60},{"id":459,"depth":155,"text":460},{"id":793,"depth":155,"text":794},{"id":1334,"depth":114,"text":1334},[1356],"微服务","2025-12-16","介绍 gRPC 的普通调用、客户端流、服务端流和双向流四种通信模式，并给出 Go 示例。",false,"md",null,{"slots":1363},{},"\u002F2025\u002F12\u002Fgrpc-4method",{"text":1366,"minutes":1367,"time":1368,"words":1369},"2 min read",1.965,117900,393,{"title":5,"description":1358},{"loc":1364},"posts\u002F2025\u002F12\u002Fgrpc-4method",[1374,1356],"gRPC","tech","2026-01-05","Y0u4wczxrfr1KVPrr_66WY8JJGgw5DGPuUoNJlvzFdQ",[1379,1384],{"title":1380,"path":1381,"stem":1382,"date":1383,"type":1375,"children":-1},"Protocol Buffers 核心语法详解","\u002F2025\u002F12\u002Fproto-syntax","posts\u002F2025\u002F12\u002Fproto-syntax","2025-12-09",{"title":1385,"path":1386,"stem":1387,"date":1388,"type":1375,"children":-1},"MCP Server 基础概念与入门实践","\u002F2025\u002F12\u002Fmcp-server-intro","posts\u002F2025\u002F12\u002Fmcp-server-intro","2025-12-28",1786555054722]