首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 方式1:变量绑定
|
||||
var name string
|
||||
flag.StringVar(&name, "name", "guest", "用户名")
|
||||
|
||||
// 方式2:指针获取
|
||||
age := flag.Int("age", 18, "用户年龄")
|
||||
enable := flag.Bool("enable", false, "是否启用功能")
|
||||
|
||||
// 解析命令行参数
|
||||
flag.Parse()
|
||||
|
||||
// 输出结果
|
||||
fmt.Printf("用户名:%s\n", name)
|
||||
fmt.Printf("年龄:%d\n", *age)
|
||||
fmt.Printf("功能启用:%t\n", *enable)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
port := flag.Int("port", 8080, "服务端口")
|
||||
host := flag.String("host", "localhost", "服务绑定主机")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// 环境变量仅覆盖未手动传参的配置
|
||||
if !flag.IsSet("port") {
|
||||
if envPort := os.Getenv("SERVICE_PORT"); envPort != "" {
|
||||
if p, err := strconv.Atoi(envPort); err == nil {
|
||||
*port = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !flag.IsSet("host") {
|
||||
if envHost := os.Getenv("SERVICE_HOST"); envHost != "" {
|
||||
*host = envHost
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("最终生效配置:主机=%s,端口=%d\n", *host, *port)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
port := flag.Int("port", 8080, "服务监听端口")
|
||||
config := flag.String("config", "./config.yaml", "配置文件路径")
|
||||
|
||||
// 重写全局帮助信息
|
||||
flag.Usage = func() {
|
||||
_, err := fmt.Fprintf(flag.CommandLine.Output(), "=== 服务启动工具 V1.0 ===\n\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = fmt.Fprintf(flag.CommandLine.Output(), "用法:%s [可选参数]\n\n", os.Args[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = fmt.Fprintf(flag.CommandLine.Output(), "参数说明:\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
flag.PrintDefaults()
|
||||
_, err = fmt.Fprintf(flag.CommandLine.Output(), "\n使用示例:\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = fmt.Fprintf(flag.CommandLine.Output(), " %s -port=8080 -config=app.yaml\n", os.Args[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("服务启动成功,端口:%d,配置文件:%s\n", *port, *config)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PortRange 自定义端口范围类型,支持 min-max 格式
|
||||
type PortRange struct {
|
||||
Min int
|
||||
Max int
|
||||
}
|
||||
|
||||
// Set 实现Value接口,完成参数解析和合法性校验
|
||||
func (p *PortRange) Set(s string) error {
|
||||
parts := strings.Split(s, "-")
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("格式错误,端口范围格式必须为 minV-max")
|
||||
}
|
||||
|
||||
var minV, maxV int
|
||||
_, err1 := fmt.Sscanf(parts[0], "%d", &minV)
|
||||
_, err2 := fmt.Sscanf(parts[1], "%d", &maxV)
|
||||
if err1 != nil || err2 != nil {
|
||||
return fmt.Errorf("端口必须为整数")
|
||||
}
|
||||
|
||||
if minV < 1 || minV > 65535 || maxV < 1 || maxV > 65535 || minV > maxV {
|
||||
return fmt.Errorf("端口范围必须在1-65535之间,且min <= max")
|
||||
}
|
||||
|
||||
p.Min = minV
|
||||
p.Max = maxV
|
||||
return nil
|
||||
}
|
||||
|
||||
// String 实现Value接口,定义默认值与字符串展示
|
||||
func (p *PortRange) String() string {
|
||||
if p.Min == 0 && p.Max == 0 {
|
||||
return "1-65535"
|
||||
}
|
||||
return fmt.Sprintf("%d-%d", p.Min, p.Max)
|
||||
}
|
||||
|
||||
// Get 实现Getter接口,返回原始类型,支持类型断言
|
||||
func (p *PortRange) Get() any {
|
||||
return *p
|
||||
}
|
||||
|
||||
func main() {
|
||||
var portRange PortRange
|
||||
flag.Var(&portRange, "port-range", "端口范围,格式:min-max")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("有效端口范围:[%d, %d]\n", portRange.Min, portRange.Max)
|
||||
fmt.Printf("类型安全取值:%#v\n", portRange.Get().(PortRange))
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
port := flag.Int("port", 8080, "服务端口")
|
||||
flag.Parse()
|
||||
|
||||
fmt.Println("动态修改前端口:", *port)
|
||||
|
||||
// 动态覆盖参数值
|
||||
if err := flag.Set("port", "9090"); err != nil {
|
||||
fmt.Println("参数设置失败:", err)
|
||||
}
|
||||
|
||||
fmt.Println("动态修改后端口:", *port)
|
||||
|
||||
// 精准查询参数元信息
|
||||
if f := flag.Lookup("port"); f != nil {
|
||||
fmt.Printf("参数详情:名称=%s, 当前值=%s, 默认值=%s, 用途=%s\n",
|
||||
f.Name, f.Value.String(), f.DefValue, f.Usage)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Environment 运行环境枚举类型
|
||||
type Environment string
|
||||
|
||||
const (
|
||||
EnvDev Environment = "dev"
|
||||
EnvTest Environment = "test"
|
||||
EnvProd Environment = "prod"
|
||||
)
|
||||
|
||||
// 合法环境白名单
|
||||
var validEnvs = map[Environment]bool{
|
||||
EnvDev: true,
|
||||
EnvTest: true,
|
||||
EnvProd: true,
|
||||
}
|
||||
|
||||
func (e *Environment) Set(s string) error {
|
||||
env := Environment(strings.ToLower(s))
|
||||
if !validEnvs[env] {
|
||||
return fmt.Errorf("无效运行环境,仅支持 dev/test/prod")
|
||||
}
|
||||
*e = env
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Environment) String() string {
|
||||
if *e == "" {
|
||||
return string(EnvDev)
|
||||
}
|
||||
return string(*e)
|
||||
}
|
||||
|
||||
func (e *Environment) Get() any {
|
||||
return *e
|
||||
}
|
||||
|
||||
func main() {
|
||||
var env Environment = EnvDev // 默认值为 dev
|
||||
flag.Var(&env, "env", "运行环境:dev/test/prod")
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("当前运行环境:%s\n", env)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 子命令标准模式:手动捕获错误,不自动退出
|
||||
fs := flag.NewFlagSet("demo", flag.ContinueOnError)
|
||||
num := fs.Int("num", 0, "数字参数")
|
||||
|
||||
// 传入非法参数
|
||||
err := fs.Parse([]string{"-num=abc"})
|
||||
if err != nil {
|
||||
fmt.Printf("参数解析失败:%v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("参数值:", *num)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 普通函数参数,传参即触发回调
|
||||
flag.Func("msg", "自定义消息参数", func(s string) error {
|
||||
fmt.Println("接收参数消息:", s)
|
||||
return nil
|
||||
})
|
||||
|
||||
// 布尔函数参数,无值传参触发
|
||||
flag.BoolFunc("debug", "开启调试模式", func(s string) error {
|
||||
fmt.Println("调试模式状态:", s)
|
||||
return nil
|
||||
})
|
||||
|
||||
flag.Parse()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// FilePath 带合法性校验的文件路径类型
|
||||
type FilePath string
|
||||
|
||||
func (f *FilePath) Set(s string) error {
|
||||
// 解析绝对路径
|
||||
absPath, err := filepath.Abs(s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("路径解析失败:%w", err)
|
||||
}
|
||||
|
||||
// 校验文件存在且为普通文件
|
||||
info, err := os.Stat(absPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("配置文件不存在:%s", absPath)
|
||||
}
|
||||
return fmt.Errorf("文件访问异常:%w", err)
|
||||
}
|
||||
if info.IsDir() {
|
||||
return fmt.Errorf("路径为目录,需传入有效文件路径:%s", absPath)
|
||||
}
|
||||
|
||||
*f = FilePath(absPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FilePath) String() string {
|
||||
return string(*f)
|
||||
}
|
||||
|
||||
func (f *FilePath) Get() any {
|
||||
return string(*f)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var configFile FilePath
|
||||
flag.Var(&configFile, "config", "必填配置文件路径")
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("加载配置文件:%s\n", configFile)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
port := flag.Int("port", 8080, "服务端口")
|
||||
flag.Parse()
|
||||
|
||||
// 获取无标记位置参数
|
||||
args := flag.Args()
|
||||
if len(args) == 0 {
|
||||
fmt.Println("请传入配置文件路径")
|
||||
return
|
||||
}
|
||||
fmt.Printf("端口:%d,配置文件:%s\n", *port, args[0])
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type StringSlice2 []string
|
||||
|
||||
func (s *StringSlice2) Set(val string) error {
|
||||
*s = append(*s, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StringSlice2) String() string {
|
||||
return strings.Join(*s, ",")
|
||||
}
|
||||
|
||||
func main() {
|
||||
var files StringSlice2
|
||||
flag.Var(&files, "file", "指定多个配置文件,可重复传参")
|
||||
flag.Parse()
|
||||
fmt.Printf("文件列表:%#v\n", files)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StringSlice 支持重复传参的字符串切片类型
|
||||
type StringSlice []string
|
||||
|
||||
// Set 实现参数追加逻辑,覆盖原生覆盖问题
|
||||
func (s *StringSlice) Set(value string) error {
|
||||
*s = append(*s, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String 实现字符串展示与零值返回
|
||||
func (s *StringSlice) String() string {
|
||||
if len(*s) == 0 {
|
||||
return "[]"
|
||||
}
|
||||
return strings.Join(*s, ",")
|
||||
}
|
||||
|
||||
// Get 实现Getter接口,返回原始切片类型
|
||||
func (s *StringSlice) Get() any {
|
||||
return []string(*s)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var files StringSlice
|
||||
var tags StringSlice
|
||||
|
||||
flag.Var(&files, "file", "指定配置文件,可重复传参")
|
||||
flag.Var(&tags, "tag", "自定义业务标签,可重复传参")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("文件列表:%v (原始类型:%T)\n", files.Get(), files.Get())
|
||||
fmt.Printf("标签列表:%v (原始类型:%T)\n", tags.Get(), tags.Get())
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 初始化子命令FlagSet
|
||||
startCmd := flag.NewFlagSet("start", flag.ContinueOnError)
|
||||
stopCmd := flag.NewFlagSet("stop", flag.ContinueOnError)
|
||||
|
||||
// 子命令私有参数
|
||||
var port int
|
||||
var config string
|
||||
startCmd.IntVar(&port, "port", 8080, "服务监听端口")
|
||||
stopCmd.StringVar(&config, "config", "./config.yaml", "服务配置文件")
|
||||
|
||||
// 校验子命令是否传入
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("可用子命令:start / stop")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 路由分发
|
||||
switch os.Args[1] {
|
||||
case "start":
|
||||
_ = startCmd.Parse(os.Args[2:])
|
||||
fmt.Printf("启动服务成功,端口:%d\n", port)
|
||||
case "stop":
|
||||
_ = stopCmd.Parse(os.Args[2:])
|
||||
fmt.Printf("停止服务,配置文件:%s\n", config)
|
||||
default:
|
||||
fmt.Printf("未知子命令:%s\n", os.Args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// GlobalOptions 全局公共参数,所有子命令共享
|
||||
type GlobalOptions struct {
|
||||
Verbose bool // 详细日志模式
|
||||
Config string // 全局配置文件
|
||||
}
|
||||
|
||||
// SubCommand 通用子命令抽象结构体
|
||||
type SubCommand struct {
|
||||
Name string
|
||||
Description string
|
||||
Flags *flag.FlagSet
|
||||
Run func([]string, GlobalOptions) error
|
||||
}
|
||||
|
||||
// 提前声明变量,避免初始化循环引用
|
||||
var commands map[string]*SubCommand
|
||||
|
||||
// init 初始化子命令,将 FlagSet 的绑定与执行逻辑分离
|
||||
func init() {
|
||||
// --- 初始化 build 命令 ---
|
||||
buildCmd := &SubCommand{
|
||||
Name: "build",
|
||||
Description: "编译构建项目",
|
||||
Flags: flag.NewFlagSet("build", flag.ContinueOnError),
|
||||
}
|
||||
var buildOutput string
|
||||
// 在外部绑定参数,而不是在 Run 里面重新创建 FlagSet
|
||||
buildCmd.Flags.StringVar(&buildOutput, "output", "./dist", "项目构建输出目录")
|
||||
buildCmd.Run = func(args []string, global GlobalOptions) error {
|
||||
if err := buildCmd.Flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("[构建成功] 输出目录:%s,全局详细日志:%t,全局配置:%s\n",
|
||||
buildOutput, global.Verbose, global.Config)
|
||||
return nil
|
||||
}
|
||||
|
||||
// --- 初始化 deploy 命令 ---
|
||||
deployCmd := &SubCommand{
|
||||
Name: "deploy",
|
||||
Description: "部署项目到环境",
|
||||
Flags: flag.NewFlagSet("deploy", flag.ContinueOnError),
|
||||
}
|
||||
var deployEnv string
|
||||
deployCmd.Flags.StringVar(&deployEnv, "env", "dev", "部署环境 dev/test/prod")
|
||||
deployCmd.Run = func(args []string, global GlobalOptions) error {
|
||||
if err := deployCmd.Flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("[部署成功] 目标环境:%s,全局配置文件:%s\n",
|
||||
deployEnv, global.Config)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 注册子命令
|
||||
commands = map[string]*SubCommand{
|
||||
"build": buildCmd,
|
||||
"deploy": deployCmd,
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 1. 初始化全局参数 FlagSet(独立隔离)
|
||||
var global GlobalOptions
|
||||
globalFlags := flag.NewFlagSet("global", flag.ContinueOnError)
|
||||
globalFlags.BoolVar(&global.Verbose, "verbose", false, "启用详细日志输出")
|
||||
globalFlags.StringVar(&global.Config, "config", "./config.yaml", "全局配置文件路径")
|
||||
|
||||
// 2. 解析全局参数
|
||||
// 注意:flag 库遇到第一个非 Flag 参数(即子命令名称)就会停止解析
|
||||
if err := globalFlags.Parse(os.Args[1:]); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
printHelp(globalFlags)
|
||||
return
|
||||
}
|
||||
fmt.Println("全局参数解析失败:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 3. 获取剩余参数(子命令 + 子命令参数)
|
||||
remainingArgs := globalFlags.Args()
|
||||
if len(remainingArgs) == 0 {
|
||||
printHelp(globalFlags)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 4. 路由分发执行子命令
|
||||
cmdName := remainingArgs[0]
|
||||
if cmd, exists := commands[cmdName]; exists {
|
||||
if err := cmd.Run(remainingArgs[1:], global); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
// 当子命令触发 -h 时,打印该子命令专属的帮助信息
|
||||
fmt.Printf("\n===== 子命令 [%s] 帮助信息 =====\n", cmd.Name)
|
||||
fmt.Printf("说明:%s\n\n用法:%s [选项]\n\n选项:\n", cmd.Description, cmd.Name)
|
||||
cmd.Flags.PrintDefaults()
|
||||
return
|
||||
}
|
||||
fmt.Printf("子命令执行失败:%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("❌ 未知子命令:%s\n", cmdName)
|
||||
printHelp(globalFlags)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// printHelp 统一打印全局帮助信息
|
||||
func printHelp(globalFlags *flag.FlagSet) {
|
||||
fmt.Println("===== 项目工程化 CLI 工具 =====")
|
||||
fmt.Println("用法:tool [全局选项] <子命令> [子命令选项]")
|
||||
fmt.Println("\n全局选项:")
|
||||
globalFlags.PrintDefaults()
|
||||
|
||||
fmt.Println("\n可用子命令:")
|
||||
for _, cmd := range commands {
|
||||
fmt.Printf(" %-10s %s\n", cmd.Name, cmd.Description)
|
||||
}
|
||||
fmt.Println("\n提示:使用 'tool <子命令> -h' 查看子命令详细帮助")
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CustomTime 自定义时间类型,复用标准库文本序列化接口
|
||||
type CustomTime time.Time
|
||||
|
||||
// MarshalText 实现文本序列化(对应默认值展示)
|
||||
func (t CustomTime) MarshalText() ([]byte, error) {
|
||||
return []byte(time.Time(t).Format(time.RFC3339)), nil
|
||||
}
|
||||
|
||||
// UnmarshalText 实现文本反序列化(参数解析核心)
|
||||
func (t *CustomTime) UnmarshalText(b []byte) error {
|
||||
parseTime, err := time.Parse(time.RFC3339, string(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*t = CustomTime(parseTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 枚举类型示例:自定义运行模式
|
||||
type RunMode string
|
||||
|
||||
const (
|
||||
ModeDev RunMode = "dev"
|
||||
ModeProd RunMode = "prod"
|
||||
)
|
||||
|
||||
func (m RunMode) MarshalText() ([]byte, error) {
|
||||
return []byte(m), nil
|
||||
}
|
||||
|
||||
func (m *RunMode) UnmarshalText(b []byte) error {
|
||||
val := RunMode(b)
|
||||
if val != ModeDev && val != ModeProd {
|
||||
return fmt.Errorf("非法运行模式,仅支持 dev/prod")
|
||||
}
|
||||
*m = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 1. 自定义时间参数 TextVar 绑定
|
||||
var execTime CustomTime
|
||||
defaultTime := CustomTime(time.Now())
|
||||
flag.TextVar(&execTime, "exec-time", defaultTime, "执行时间(RFC3339格式)")
|
||||
|
||||
// 2. 自定义枚举参数 TextVar 绑定
|
||||
var runMode RunMode
|
||||
flag.TextVar(&runMode, "mode", ModeDev, "运行模式 dev/prod")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("运行模式:%s\n", runMode)
|
||||
fmt.Printf("执行时间:%s\n", time.Time(execTime).Format(time.RFC3339))
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// PortValue 自定义端口类型,实现flag.Value接口
|
||||
type PortValue int
|
||||
|
||||
func (p *PortValue) Set(s string) error {
|
||||
var port int
|
||||
_, err := fmt.Sscanf(s, "%d", &port)
|
||||
if err != nil || port < 1 || port > 65535 {
|
||||
return fmt.Errorf("非法端口,必须为1-65535整数")
|
||||
}
|
||||
*p = PortValue(port)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PortValue) String() string {
|
||||
return fmt.Sprintf("%d", *p)
|
||||
}
|
||||
|
||||
// EnvValue 枚举环境校验类型
|
||||
type EnvValue string
|
||||
|
||||
func (e *EnvValue) Set(s string) error {
|
||||
if s != "dev" && s != "prod" {
|
||||
return fmt.Errorf("仅支持 dev/prod 环境")
|
||||
}
|
||||
*e = EnvValue(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EnvValue) String() string {
|
||||
return string(*e)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var port PortValue
|
||||
var env EnvValue
|
||||
flag.Var(&port, "port", "服务端口 1-65535")
|
||||
flag.Var(&env, "env", "运行环境 dev/prod")
|
||||
config := flag.String("config", "", "配置文件路径(必填)")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// 后置非空校验
|
||||
if *config == "" {
|
||||
fmt.Println("错误:config 参数不能为空")
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("环境:%s,端口:%d,配置:%s\n", env, port, *config)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 定义基础参数
|
||||
flag.Int("port", 8080, "服务监听端口")
|
||||
flag.String("host", "localhost", "服务绑定主机")
|
||||
flag.Bool("debug", false, "开启调试模式")
|
||||
|
||||
// 解析参数
|
||||
flag.Parse()
|
||||
|
||||
fmt.Println("=== 所有已定义参数(含默认值)===")
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Printf("参数名:%-10s 默认值:%-10s 说明:%s\n", f.Name, f.DefValue, f.Usage)
|
||||
})
|
||||
|
||||
fmt.Println("\n=== 用户主动传入的参数===")
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
fmt.Printf("参数名:%-10s 当前值:%-10s 已修改:%v\n", f.Name, f.Value.String(), f.Value.String() != f.DefValue)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user