[{"data":1,"prerenderedAt":495},["ShallowReactive",2],{"content:\u002F2025\u002F11\u002Fwhat-is-webhook":3,"surround:\u002F2025\u002F11\u002Fwhat-is-webhook":484},{"id":4,"title":5,"body":6,"categories":462,"date":464,"description":465,"draft":466,"extension":467,"image":468,"meta":469,"navigation":79,"path":471,"permalink":468,"published":468,"readingTime":472,"recommend":468,"references":468,"seo":477,"sitemap":478,"stem":479,"tags":480,"type":482,"updated":464,"__hash__":483},"content\u002Fposts\u002F2025\u002F11\u002Fwhat-is-webhook.md","Webhook 工作原理与 Go 实现",{"type":7,"value":8,"toc":456},"minimark",[9,13,17,21,31,34,48,51,452],[10,11,12],"h2",{"id":12},"概念",[14,15,16],"p",{},"Webhook 属于一种事件驱动的消息推送机制。当特定事件被触发时，事件源会主动向预先配置的 webhook URL 发起 HTTP 请求。远程服务在收到请求后，会根据请求中携带的参数进行解析，并按照业务逻辑完成相应处理。",[10,18,20],{"id":19},"webhook-和-api-的区别","webhook 和 api 的区别",[22,23,24,28],"ul",{},[25,26,27],"li",{},"webhook 是主动推送的机制，主动向预设 url 发请求",[25,29,30],{},"api 是需要被动请求的，需要调用方手动请求",[10,32,33],{"id":33},"具体使用场景",[22,35,36,39,42,45],{},[25,37,38],{},"支付后，发送通知给商家出货",[25,40,41],{},"发博客后，主动发邮件",[25,43,44],{},"日志告警，主动发送到钉钉机器人",[25,46,47],{},"客服消息，主动推送到 n8n 工作流推送到飞书群",[10,49,50],{"id":50},"代码示例",[52,53,58],"pre",{"className":54,"code":55,"language":56,"meta":57,"style":57},"language-go shiki shiki-themes github-light github-dark","package main\n\nimport \"github.com\u002Fgin-gonic\u002Fgin\"\n\ntype WebhookRequest struct {\n    Event string `json:\"event\" binding:\"required\"`\n}\n\nfunc main() {\n    r := gin.Default()\n    r.POST(\"\u002Fwebhook\", func(c *gin.Context) {\n        var req WebhookRequest\n        if err := c.ShouldBindJSON(&req); err != nil {\n            c.JSON(400, gin.H{\"error\": err.Error()})\n            return\n        }\n        webhookEvent := req.Event\n        c.String(200, \"webhook event: %s\", webhookEvent)\n    })\n    r.Run(\":8080\")\n}\n","go","",[59,60,61,74,81,97,102,122,138,144,149,168,191,237,253,298,348,360,371,386,419,430,447],"code",{"__ignoreMap":57},[62,63,66,70],"span",{"class":64,"data-line":65,"line":65},"line",1,[62,67,69],{"class":68},"szBVR","package",[62,71,73],{"class":72},"sScJk"," main\n",[62,75,77],{"class":64,"data-line":76,"line":76},2,[62,78,80],{"emptyLinePlaceholder":79},true,"\n",[62,82,84,87,91,94],{"class":64,"data-line":83,"line":83},3,[62,85,86],{"class":68},"import",[62,88,90],{"class":89},"sZZnC"," \"",[62,92,93],{"class":72},"github.com\u002Fgin-gonic\u002Fgin",[62,95,96],{"class":89},"\"\n",[62,98,100],{"class":64,"data-line":99,"line":99},4,[62,101,80],{"emptyLinePlaceholder":79},[62,103,105,108,111,114,118],{"class":64,"data-line":104,"line":104},5,[62,106,107],{"class":68},"type",[62,109,110],{"class":72}," WebhookRequest",[62,112,113],{"class":68}," struct",[62,115,117],{"class":116},"sVt8B"," ",[62,119,121],{"class":120},"sSDpw","{\n",[62,123,125,129,132,135],{"class":64,"data-line":124,"line":124},6,[62,126,128],{"class":127},"indent","    ",[62,130,131],{"class":116},"Event ",[62,133,134],{"class":68},"string",[62,136,137],{"class":89}," `json:\"event\" binding:\"required\"`\n",[62,139,141],{"class":64,"data-line":140,"line":140},7,[62,142,143],{"class":120},"}\n",[62,145,147],{"class":64,"data-line":146,"line":146},8,[62,148,80],{"emptyLinePlaceholder":79},[62,150,152,155,158,161,164,166],{"class":64,"data-line":151,"line":151},9,[62,153,154],{"class":68},"func",[62,156,157],{"class":72}," main",[62,159,160],{"class":120},"(",[62,162,163],{"class":120},")",[62,165,117],{"class":116},[62,167,121],{"class":120},[62,169,171,173,176,179,182,185,188],{"class":64,"data-line":170,"line":170},10,[62,172,128],{"class":127},[62,174,175],{"class":116},"r ",[62,177,178],{"class":68},":=",[62,180,181],{"class":116}," gin.",[62,183,184],{"class":72},"Default",[62,186,160],{"class":187},"sJX2D",[62,189,190],{"class":187},")\n",[62,192,194,196,199,202,204,207,210,212,215,219,222,225,228,231,233,235],{"class":64,"data-line":193,"line":193},11,[62,195,128],{"class":127},[62,197,198],{"class":116},"r.",[62,200,201],{"class":72},"POST",[62,203,160],{"class":187},[62,205,206],{"class":89},"\"\u002Fwebhook\"",[62,208,209],{"class":116},", ",[62,211,154],{"class":68},[62,213,160],{"class":214},"sqkie",[62,216,218],{"class":217},"s4XuR","c",[62,220,221],{"class":68}," *",[62,223,224],{"class":72},"gin",[62,226,227],{"class":116},".",[62,229,230],{"class":72},"Context",[62,232,163],{"class":214},[62,234,117],{"class":116},[62,236,121],{"class":214},[62,238,240,242,244,247,250],{"class":64,"data-line":239,"line":239},12,[62,241,128],{"class":127},[62,243,128],{"class":127},[62,245,246],{"class":68},"var",[62,248,249],{"class":116}," req ",[62,251,252],{"class":72},"WebhookRequest\n",[62,254,256,258,260,263,266,268,271,274,276,279,282,284,287,290,294,296],{"class":64,"data-line":255,"line":255},13,[62,257,128],{"class":127},[62,259,128],{"class":127},[62,261,262],{"class":68},"if",[62,264,265],{"class":116}," err ",[62,267,178],{"class":68},[62,269,270],{"class":116}," c.",[62,272,273],{"class":72},"ShouldBindJSON",[62,275,160],{"class":120},[62,277,278],{"class":68},"&",[62,280,281],{"class":116},"req",[62,283,163],{"class":120},[62,285,286],{"class":116},"; err ",[62,288,289],{"class":68},"!=",[62,291,293],{"class":292},"sj4cs"," nil",[62,295,117],{"class":116},[62,297,121],{"class":120},[62,299,301,303,305,307,310,313,315,318,320,322,324,327,330,333,336,339,341,343,346],{"class":64,"data-line":300,"line":300},14,[62,302,128],{"class":127},[62,304,128],{"class":127},[62,306,128],{"class":127},[62,308,309],{"class":116},"c.",[62,311,312],{"class":72},"JSON",[62,314,160],{"class":187},[62,316,317],{"class":292},"400",[62,319,209],{"class":116},[62,321,224],{"class":72},[62,323,227],{"class":116},[62,325,326],{"class":72},"H",[62,328,329],{"class":214},"{",[62,331,332],{"class":89},"\"error\"",[62,334,335],{"class":116},": err.",[62,337,338],{"class":72},"Error",[62,340,160],{"class":120},[62,342,163],{"class":120},[62,344,345],{"class":214},"}",[62,347,190],{"class":187},[62,349,351,353,355,357],{"class":64,"data-line":350,"line":350},15,[62,352,128],{"class":127},[62,354,128],{"class":127},[62,356,128],{"class":127},[62,358,359],{"class":68},"return\n",[62,361,363,365,367,369],{"class":64,"data-line":362,"line":362},16,[62,364,128],{"class":127},[62,366,128],{"class":127},[62,368,57],{"class":116},[62,370,143],{"class":120},[62,372,374,376,378,381,383],{"class":64,"data-line":373,"line":373},17,[62,375,128],{"class":127},[62,377,128],{"class":127},[62,379,380],{"class":116},"webhookEvent ",[62,382,178],{"class":68},[62,384,385],{"class":116}," req.Event\n",[62,387,389,391,393,395,398,400,403,405,408,411,414,417],{"class":64,"data-line":388,"line":388},18,[62,390,128],{"class":127},[62,392,128],{"class":127},[62,394,309],{"class":116},[62,396,397],{"class":72},"String",[62,399,160],{"class":120},[62,401,402],{"class":292},"200",[62,404,209],{"class":116},[62,406,407],{"class":89},"\"webhook event: ",[62,409,410],{"class":292},"%s",[62,412,413],{"class":89},"\"",[62,415,416],{"class":116},", webhookEvent",[62,418,190],{"class":120},[62,420,422,424,426,428],{"class":64,"data-line":421,"line":421},19,[62,423,128],{"class":127},[62,425,57],{"class":116},[62,427,345],{"class":214},[62,429,190],{"class":187},[62,431,433,435,437,440,442,445],{"class":64,"data-line":432,"line":432},20,[62,434,128],{"class":127},[62,436,198],{"class":116},[62,438,439],{"class":72},"Run",[62,441,160],{"class":187},[62,443,444],{"class":89},"\":8080\"",[62,446,190],{"class":187},[62,448,450],{"class":64,"data-line":449,"line":449},21,[62,451,143],{"class":120},[453,454,455],"style",{},"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 .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sSDpw, html code.shiki .sSDpw{--shiki-default:#005cc5;--shiki-dark:#79b8ff}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 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 .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);}",{"title":57,"searchDepth":99,"depth":99,"links":457},[458,459,460,461],{"id":12,"depth":76,"text":12},{"id":19,"depth":76,"text":20},{"id":33,"depth":76,"text":33},{"id":50,"depth":76,"text":50},[463],"工程实践","2025-11-18","介绍 Webhook 的事件通知机制、典型使用场景，并使用 Go 和 Gin 实现简单的回调接口。",false,"md",null,{"slots":470},{},"\u002F2025\u002F11\u002Fwhat-is-webhook",{"text":473,"minutes":474,"time":475,"words":476},"2 min read",1.2,72000,240,{"title":5,"description":465},{"loc":471},"posts\u002F2025\u002F11\u002Fwhat-is-webhook",[481],"webhook","tech","iAgS1ehvDAMKw02wNcWK01gfnS7MwqXS2t2cqdXdENE",[485,490],{"title":486,"path":487,"stem":488,"date":489,"type":482,"children":-1},"GitLab Runner 使用与 CICD 全面指南","\u002F2025\u002F11\u002Fgitlab-ci","posts\u002F2025\u002F11\u002Fgitlab-ci","2025-11-10",{"title":491,"path":492,"stem":493,"date":494,"type":482,"children":-1},"短视频的推荐算法","\u002F2025\u002F12\u002Frecemmend-algorithm","posts\u002F2025\u002F12\u002Frecemmend-algorithm","2025-12-02",1786555054789]