You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go中处理完一次请求后停止HTTP服务?

嘿,这个需求太常见了——做OAuth或者第三方认证的时候,经常需要临时开个本地端口收回调token,用完就关。我给你两种实用的Go实现方式,看你偏好哪种:

方法一:优雅关闭服务(推荐)

这种方式会等当前请求完全处理完再终止服务,不会出现token还没拿到就中断的情况,非常稳妥。

package main

import (
	"context"
	"fmt"
	"net/http"
	"sync"
)

func main() {
	// 用WaitGroup确保请求处理完成后再关服务
	var wg sync.WaitGroup
	wg.Add(1)

	mux := http.NewServeMux()
	mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
		defer wg.Done()
		// 这里处理你的token逻辑,比如从URL参数里取
		token := r.URL.Query().Get("token")
		fmt.Printf("成功拿到Token:%s\n", token)
		w.Write([]byte("认证完成!这个页面可以关闭了"))

		// 启动goroutine关闭服务,避免阻塞当前请求
		go func() {
			wg.Wait()
			if err := server.Shutdown(context.Background()); err != nil {
				fmt.Printf("关闭服务时出错:%v\n", err)
			}
		}()
	})

	server := &http.Server{
		Addr:    ":8080",
		Handler: mux,
	}

	fmt.Println("临时服务启动,监听localhost:8080...")
	// ListenAndServe会阻塞直到服务被Shutdown
	if err := server.ListenAndServe(); err != http.ErrServerClosed {
		fmt.Printf("服务意外终止:%v\n", err)
	}
	fmt.Println("服务已正常关闭")
}

关键点说明:

  • sync.WaitGroup用来等待回调请求处理完毕,确保我们拿到token后再关服务
  • 必须在goroutine里调用Shutdown,不然当前请求会被阻塞,客户端收不到响应
  • Shutdown会优雅关闭所有连接,不会强制中断正在处理的请求
方法二:快速终止服务(简洁版)

如果你的场景明确只需要处理一次请求,不需要考虑优雅关闭,这种方式更简单直接。

package main

import (
	"fmt"
	"net"
	"net/http"
)

func main() {
	mux := http.NewServeMux()
	var listener net.Listener

	mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
		// 提取并处理token
		token := r.URL.Query().Get("token")
		fmt.Printf("Token已获取:%s\n", token)
		w.Write([]byte("认证成功!"))

		// 直接关闭监听,服务立刻停止
		if listener != nil {
			if err := listener.Close(); err != nil {
				fmt.Printf("关闭监听失败:%v\n", err)
			}
		}
	})

	var err error
	// 手动创建Listener,这样能拿到引用用来关闭
	listener, err = net.Listen("tcp", ":8080")
	if err != nil {
		fmt.Printf("监听端口失败:%v\n", err)
		return
	}

	fmt.Println("等待第三方回调...")
	// Serve会一直运行直到Listener被关闭
	if err := http.Serve(listener, mux); err != nil && err != http.ErrServerClosed {
		fmt.Printf("服务异常终止:%v\n", err)
	}
	fmt.Println("服务已停止")
}

关键点说明:

  • 手动创建net.Listener代替ListenAndServe,这样我们能主动关闭它
  • 在回调handler里调用listener.Close(),http.Serve会立刻返回,服务终止
  • 这种方式会直接断开所有连接,适合明确只处理一次请求的场景

额外注意事项:

  • 确保第三方服务的回调地址和你代码里的一致(比如http://localhost:8080/callback)
  • 如果是OAuth认证,回调路径要和你在第三方平台配置的完全匹配
  • 第一种方法更通用,哪怕出现意外多请求也不会出问题;第二种方法更轻量,适合简单场景

内容的提问来源于stack exchange,提问作者Jonas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:05:11