golang轻量级单文件HTTP服务器模板插件kickstart.go的使用

golang轻量级单文件HTTP服务器模板插件kickstart.go的使用

概述

kickstart.go是一个极简的Go语言HTTP服务器模板,具有以下特点:

  • 代码量小(少于300行)
  • 单文件实现
  • 仅依赖标准库

这不是一个框架,而是构建Go语言HTTP服务的起点。该项目在GopherCon Korea 2024上首次展示。

主要特性

  • 优雅关闭:处理SIGINTSIGTERM信号实现优雅关闭
  • 健康检查端点:返回服务器健康状态,包括版本和修订信息
  • OpenAPI端点:使用embed包提供OpenAPI规范
  • 调试信息:提供各种调试指标,包括pprofexpvars
  • 访问日志:使用slog记录HTTP请求详情
  • 崩溃恢复:优雅地捕获和记录HTTP处理程序中的panic
  • 完整文档:包含所有导出函数和类型的注释和文档

快速开始

要求

Go 1.22或更高版本

构建并运行服务器

$ make run

这将构建服务器并在8080端口上运行

端点说明

  • GET /health: 返回服务健康状态,包括版本、修订和修改状态
  • GET /openapi.yaml: 返回服务的OpenAPI规范
  • GET /debug/pprof: 返回pprof调试信息
  • GET /debug/vars: 返回expvars调试信息

完整示例代码

package main

import (
	"context"
	"embed"
	"errors"
	"flag"
	"fmt"
	"io/fs"
	"log/slog"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

//go:embed openapi.yaml
var openapiSpec embed.FS

func main() {
	var port int
	flag.IntVar(&port, "port", 8080, "HTTP server port")
	flag.Parse()

	// 创建HTTP服务器
	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", port),
		Handler: newRouter(),
	}

	// 优雅关闭处理
	done := make(chan os.Signal, 1)
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		slog.Info("Starting server", "port", port)
		if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			slog.Error("Server error", "error", err)
		}
	}()

	<-done
	slog.Info("Server is shutting down...")

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		slog.Error("Server shutdown error", "error", err)
	}
	slog.Info("Server stopped")
}

func newRouter() *http.ServeMux {
	mux := http.NewServeMux()
	
	// 健康检查端点
	mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.Write([]byte(`{"status": "ok"}`))
	})
	
	// OpenAPI端点
	mux.HandleFunc("GET /openapi.yaml", func(w http.ResponseWriter, r *http.Request) {
		spec, _ := fs.ReadFile(openapiSpec, "openapi.yaml")
		w.Header().Set("Content-Type", "text/yaml")
		w.Write(spec)
	})
	
	// 调试端点
	mux.HandleFunc("GET /debug/pprof/", func(w http.ResponseWriter, r *http.Request) {
		http.DefaultServeMux.ServeHTTP(w, r)
	})
	
	mux.HandleFunc("GET /debug/vars", func(w http.ResponseWriter, r *http.Request) {
		http.DefaultServeMux.ServeHTTP(w, r)
	})
	
	return mux
}

如何开始新项目

  1. 使用此模板创建新仓库
  2. 或者fork仓库并根据需要进行修改
  3. 查找并替换所有字符串raeperd/kickstart.go为你的仓库/镜像名称

如何移除所有注释

$ sed -i '' '/^\/\/go:embed/! {/^\s*\/\/.*$/d; /^\s*\/\*\*/,/\*\//d;}' *.go

参考

  • GopherCon Korean 2024 Session (韩语)
  • How I write HTTP services in Go after 13 years | Grafana Labs

更多关于golang轻量级单文件HTTP服务器模板插件kickstart.go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang轻量级单文件HTTP服务器模板插件kickstart.go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用 kickstart.go 创建轻量级 HTTP 服务器

kickstart.go 是一个简洁的 Go 语言单文件 HTTP 服务器模板,非常适合快速启动小型 Web 项目或 API 服务。下面我将详细介绍如何使用它。

基本使用方法

首先,获取 kickstart.go 文件(假设你已经有了这个模板文件),然后可以这样使用:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	// 设置路由
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "欢迎使用 kickstart.go HTTP 服务器!")
	})

	// 启动服务器
	fmt.Println("服务器启动在 :8080...")
	http.ListenAndServe(":8080", nil)
}

增强功能模板

下面是一个更完整的 kickstart.go 模板,包含常用功能:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"
)

// 配置结构体
type Config struct {
	Port    string `json:"port"`
	Env     string `json:"env"`
	Version string `json:"version"`
}

// 应用结构体
type Application struct {
	Config Config
	Logger *log.Logger
}

func main() {
	// 初始化配置
	cfg := Config{
		Port:    ":8080",
		Env:     "development",
		Version: "1.0.0",
	}

	// 初始化应用
	app := &Application{
		Config: cfg,
		Logger: log.New(log.Writer(), "kickstart: ", log.LstdFlags|log.Lshortfile),
	}

	// 设置路由
	mux := http.NewServeMux()
	mux.HandleFunc("/", app.homeHandler)
	mux.HandleFunc("/api/data", app.dataHandler)
	mux.HandleFunc("/health", app.healthHandler)

	// 创建自定义服务器
	srv := &http.Server{
		Addr:         cfg.Port,
		Handler:      app.logRequest(mux),
		IdleTimeout:  time.Minute,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 30 * time.Second,
	}

	// 启动服务器
	app.Logger.Printf("启动 %s 服务器在 %s", cfg.Env, cfg.Port)
	err := srv.ListenAndServe()
	app.Logger.Fatal(err)
}

// 处理器函数
func (app *Application) homeHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	fmt.Fprintf(w, "欢迎使用 kickstart.go (v%s)", app.Config.Version)
}

func (app *Application) dataHandler(w http.ResponseWriter, r *http.Request) {
	data := map[string]interface{}{
		"status":  "success",
		"message": "这是API数据",
		"version": app.Config.Version,
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(data)
}

func (app *Application) healthHandler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("OK"))
}

// 中间件:记录请求
func (app *Application) logRequest(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		next.ServeHTTP(w, r)
		app.Logger.Printf("%s %s %s %v", r.Method, r.URL.Path, r.RemoteAddr, time.Since(start))
	})
}

功能特点

  1. 简洁结构:单文件包含所有必要组件
  2. 配置管理:使用结构体管理配置
  3. 日志记录:内置请求日志中间件
  4. 优雅超时:设置读写和空闲超时
  5. 路由处理:支持多个路由处理器
  6. JSON API:内置JSON响应支持

如何扩展

你可以根据需要添加以下功能:

  1. 添加数据库支持
import "database/sql"
import _ "github.com/lib/pq"

// 在Application结构体中添加
type Application struct {
	Config Config
	Logger *log.Logger
	DB     *sql.DB
}

// 初始化数据库
db, err := sql.Open("postgres", "your-connection-string")
if err != nil {
    log.Fatal(err)
}
app.DB = db
  1. 添加环境变量支持
import "os"

// 在配置中
Port:    getEnv("PORT", "8080"),
Env:     getEnv("ENV", "development"),

// 辅助函数
func getEnv(key, defaultValue string) string {
    if value, exists := os.LookupEnv(key); exists {
        return value
    }
    return defaultValue
}
  1. 添加静态文件服务
// 在路由设置中添加
fs := http.FileServer(http.Dir("./static"))
mux.Handle("/static/", http.StripPrefix("/static", fs))

这个 kickstart.go 模板提供了足够的基础功能,同时保持简洁,你可以根据项目需求轻松扩展它。

回到顶部