golang notes(12)---use cobra+viper to replace qt

本文介绍了如何用Cobra和Viper库替换基于qt的GUI,以专注于问题解决。通过Cobra创建命令行界面,Viper管理配置文件。例如,使用'ngapp nrrg conf freqband'命令获取当前设置,'ngapp nrrg conf freqband --opBand=n78'进行配置。代码示例展示了子命令的组织方式和Viper的绑定结构。Go语言在正确利用工具后,比Python更优雅且效率更高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In order to focus on problem-solving, I’ve decided to use Cobra+Viper to replace existing thereceipe/qt GUI.

Cobra: https://github.com/spf13/cobra
Viper: https://github.com/spf13/viper

For example:

  • Use cmd ‘ngapp nrrg conf freqband -h’ to get help
D:\dev\go\src\github.com\zhenggao2\ngapp>ngapp nrrg conf freqband -h
nrrg conf freqband can be used to get/set frequency-band related network configurations.

Usage:
  ngapp nrrg conf freqband [flags]

Flags:
      --opBand string   Operating band (default "n41")
  -h, --help            help for freqband

Global Flags:
  -c, --config string   config file (default is $HOME/.ngapp.yaml)
  • Use cmd ‘ngapp nrrg conf freqband’ to get current settings:
D:\dev\go\src\github.com\zhenggao2\ngapp>ngapp nrrg conf freqband
Flag           Type      Current Value    Modifiable
opBand         string    n41              true
_duplexMode    string    TDD              false
_maxDlFreq     int       2690             false
_freqRange     string    FR1              false
  • Use cmd ‘ngapp nrrg conf freqband --opBand=n78’ to configure modifiable flag opBand:
D:\dev\go\src\github.com\zhenggao2\ngapp>ngapp nrrg conf freqband --opBand=n78
nrgrid.FreqBandInfo: {3300 MHz-3800 MHz 3300 MHz-3800 MHz TDD 3800}
Available SSB scs: 30KHz
RMSI scs(subcarrierSpacingCommon of MIB) range: 15KHz,30KHz
carrier scs(subcarrierSpacing of SCS-SpecificCarrier) range: 15KHz,30KHz,60KHz
nrgrid.RachInfo: {B4 2 [1] [9] 0 1 1 12}
PRACH scs(msg1-SubcarrierSpacing of RACH-ConfigCommon) range: 15KHz,30KHz
Flag           Type      Current Value    Modifiable
opBand         string    n78              true
_duplexMode    string    TDD              false
_maxDlFreq     int       3800             false
_freqRange     string    FR1              false

Now I will introduce the framework:

  1. Former GUI settings are orgnized into separate sub-command:
// nrrgCmd.init
func init() {
	nrrgConfCmd.AddCommand(confFreqBandCmd)
	nrrgConfCmd.AddCommand(confSsbGridCmd)
	nrrgConfCmd.AddCommand(confSsbBurstCmd)
	nrrgConfCmd.AddCommand(confMibCmd)
	nrrgConfCmd.AddCommand(confCarrierGridCmd)
	nrrgConfCmd.AddCommand(confCommonSettingCmd)
	nrrgConfCmd.AddCommand(confCss0Cmd)
	nrrgConfCmd.AddCommand(confCoreset1Cmd)
	nrrgConfCmd.AddCommand(confUssCmd)
	nrrgConfCmd.AddCommand(confDci10Cmd)
	nrrgConfCmd.AddCommand(confDci11Cmd)
	nrrgConfCmd.AddCommand(confMsg3Cmd)
	nrrgConfCmd.AddCommand(confDci01Cmd)
	nrrgConfCmd.AddCommand(confBwpCmd)
	nrrgConfCmd.AddCommand(confRachCmd)
	nrrgConfCmd.AddCommand(confDmrsCommonCmd)
	nrrgConfCmd.AddCommand(confDmrsPdschCmd)
	nrrgConfCmd.AddCommand(confPtrsPdschCmd)
	nrrgConfCmd.AddCommand(confDmrsPuschCmd)
	nrrgConfCmd.AddCommand(confPtrsPuschCmd)
	nrrgConfCmd.AddCommand(confPdschCmd)
	nrrgConfCmd.AddCommand(confPuschCmd)
	nrrgConfCmd.AddCommand(confNzpCsiRsCmd)
	nrrgConfCmd.AddCommand(confTrsCmd)
	nrrgConfCmd.AddCommand(confCsiImCmd)
	nrrgConfCmd.AddCommand(confCsiReportCmd)
	nrrgConfCmd.AddCommand(confSrsCmd)
	nrrgConfCmd.AddCommand(confPucchCmd)
	nrrgConfCmd.AddCommand(confAdvancedCmd)
	nrrgCmd.AddCommand(nrrgConfCmd)
	nrrgCmd.AddCommand(nrrgSimCmd)
	rootCmd.AddCommand(nrrgCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// nrrgCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	initConfFreqBandCmd()
	initConfSsbGridCmd()
	initConfSsbBurstCmd()
	initConfMibCmd()
	initConfCarrierGridCmd()
	initConfCommonSettingCmd()
	initConfCss0Cmd()
	initConfCoreset1Cmd()
	initConfUssCmd()
	initConfDci10Cmd()
	initConfDci11Cmd()
	initConfMsg3Cmd()
	initConfDci01Cmd()
	initConfBwpCmd()
	initConfRachCmd()
	initConfDmrsCommonCmd()
	initConfDmrsPdschCmd()
	initConfPtrsPdschCmd()
	initConfDmrsPuschCmd()
	initConfPtrsPuschCmd()
	initConfPdschCmd()
	initConfPuschCmd()
	initConfNzpCsiRsCmd()
	initConfTrsCmd()
	initConfCsiImCmd()
	initConfCsiReportCmd()
	initConfSrsCmd()
	initConfPucchCmd()
	initConfAdvancedCmd()
}

Here is the example code for initConfFreqBandCmd:

  • flags started with underscore(’_’) are hidden and are designed to be unmodifiable
  • viper binding is orgnized as: app.subcmd.flags-of-subcmd, and configuration file is YAML format by default.
func initConfFreqBandCmd() {
	confFreqBandCmd.Flags().StringVar(&flags.freqBand.opBand, "opBand", "n41", "Operating band")
	confFreqBandCmd.Flags().StringVar(&flags.freqBand._duplexMode, "_duplexMode", "TDD", "Duplex mode")
	confFreqBandCmd.Flags().IntVar(&flags.freqBand._maxDlFreq, "_maxDlFreq", 2690, "Maximum DL frequency(MHz)")
	confFreqBandCmd.Flags().StringVar(&flags.freqBand._freqRange, "_freqRange", "FR1", "Frequency range(FR1/FR2)")
	confFreqBandCmd.Flags().SortFlags = false
	viper.BindPFlag("nrrg.freqBand.opBand", confFreqBandCmd.Flags().Lookup("opBand"))
	viper.BindPFlag("nrrg.freqBand._duplexMode", confFreqBandCmd.Flags().Lookup("_duplexMode"))
	viper.BindPFlag("nrrg.freqBand._maxDlFreq", confFreqBandCmd.Flags().Lookup("_maxDlFreq"))
	viper.BindPFlag("nrrg.freqBand._freqRange", confFreqBandCmd.Flags().Lookup("_freqRange"))
	confFreqBandCmd.Flags().MarkHidden("_duplexMode")
	confFreqBandCmd.Flags().MarkHidden("_maxDlFreq")
	confFreqBandCmd.Flags().MarkHidden("_freqRange")
}
  1. per subcmd implementation example:
  • In PreRun, call loadFlags function to reload all flags from viper configuration file.
var confFreqBandCmd = &cobra.Command{
	Use:   "freqband",
	Short: "",
	Long: `nrrg conf freqband can be used to get/set frequency-band related network configurations.`,
	PreRun: func(cmd *cobra.Command, args []string) {
	    loadFlags()
	},
	Run: func(cmd *cobra.Command, args []string) {
	}
  • In Run, implement procedures when certain flag is Changed.
  • Use viper.WatchConfig() and viper.WriteConfig() to keep flags and viper configuration file synchronized.
Run: func(cmd *cobra.Command, args []string) {
		viper.WatchConfig()

		if cmd.Flags().Lookup("opBand").Changed {
			band := flags.freqBand.opBand
			p, exist := nrgrid.OpBands[band]
			if !exist {
				fmt.Println("Invalid frequency band(FreqBandIndicatorNR):", band)
				return
			}

			if p.DuplexMode == "SUL" || p.DuplexMode == "SDL" {
				fmt.Println(p.DuplexMode, "is not supported!")
				return
			}

			fmt.Println("nrgrid.FreqBandInfo:", *p)

			// update band info
			flags.freqBand._duplexMode = p.DuplexMode
			flags.freqBand._maxDlFreq = p.MaxDlFreq

			v, _ := strconv.Atoi(band[1:])
			if v >= 1 && v <= 256 {
				flags.freqBand._freqRange = "FR1"
			} else {
				flags.freqBand._freqRange = "FR2"
			}

			// update ssb scs
			var ssbScsSet []string
			for _, v := range nrgrid.SsbRasters[band] {
				ssbScsSet = append(ssbScsSet, v[0])
			}
			fmt.Println("Available SSB scs:", strings.Join(ssbScsSet, ","))

			// update rmsi scs and carrier scs
			var rmsiScsSet []string
			var carrierScsSet []string
			if flags.freqBand._freqRange == "FR1" {
				rmsiScsSet = append(rmsiScsSet, []string{"15KHz", "30KHz"}...)

				scsFr1 := []int{15, 30, 60}
				for _, scs := range scsFr1 {
					key := fmt.Sprintf("%v_%v", band, scs)
					valid := false
					for _, i := range nrgrid.BandScs2BwFr1[key] {
					    if i > 0 {
					    	valid = true
					    	break
						}
					}
					if valid {
						carrierScsSet = append(carrierScsSet, fmt.Sprintf("%vKHz", scs))
					}
				}
			} else {
				rmsiScsSet = append(rmsiScsSet, []string{"60KHz", "120KHz"}...)
				carrierScsSet = append(carrierScsSet, []string{"60KHz", "120KHz"}...)
			}
			fmt.Println("RMSI scs(subcarrierSpacingCommon of MIB) range:", strings.Join(rmsiScsSet, ","))
			fmt.Println("carrier scs(subcarrierSpacing of SCS-SpecificCarrier) range:", strings.Join(carrierScsSet, ","))

			// update rach info
			err := updateRach()
			if err != nil {
				fmt.Print(err.Error())
				return
			}
		}

	    print(cmd, args)
		viper.WriteConfig()
	},
  1. Thoughts on Go vs Python:
    I am actually translating former Python codes into Go codes. With the right Wheels, Go is more elegant and much more efficient than Python.

(to be continued)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值