项目文件夹

文件
Asim Aslam 3e885308a0 lint: clear the golangci-lint backlog and enforce a blocking lint in CI (#2995)
Fixes #2988. Brings 'golangci-lint run ./...' to zero issues (was ~373):

- errcheck: explicitly ignore fire-and-forget calls with '_ =' (and a small
  errcheck.exclude-functions list for response writes — json Encoder.Encode,
  http ResponseWriter.Write, fmt.Fprint*); genuine cases handled.
- unused: remove dead code (unexported decls and dead test helpers) and the
  imports they orphaned.
- staticcheck: ST1005 error strings, ST1016 receiver names, S1000/S1017/S1019/
  S1023 simplifications, SA4004/SA4006/SA4010 dead code, SA1021 net.IP.Equal,
  SA6002 (store *[]byte in sync.Pool).
- govet: fix a context leak (lostcancel) in internal/util/mdns and move
  t.Fatal/Fatalf out of goroutines (testinggoroutine) in tests.
- ineffassign, unconvert: mechanical fixes.

CI: the Lint workflow now runs a blocking full-tree 'golangci-lint run' on
pushes and PRs (dropped only-new-issues now that the tree is clean).

Verified: go build, go vet, test compilation, and unit tests for the
behaviourally-touched packages all pass.


Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 18:51:30 +01:00

103 行
1.8 KiB
Go

package flag
import (
"errors"
"flag"
"strings"
"time"
"dario.cat/mergo"
"go-micro.dev/v6/config/source"
)
type flagsrc struct {
opts source.Options
}
func (fs *flagsrc) Read() (*source.ChangeSet, error) {
if !flag.Parsed() {
return nil, errors.New("flags not parsed")
}
var changes map[string]interface{}
visitFn := func(f *flag.Flag) {
n := strings.ToLower(f.Name)
keys := strings.FieldsFunc(n, split)
reverse(keys)
tmp := make(map[string]interface{})
for i, k := range keys {
if i == 0 {
tmp[k] = f.Value
continue
}
tmp = map[string]interface{}{k: tmp}
}
_ = mergo.Map(&changes, tmp) // need to sort error handling
}
unset, ok := fs.opts.Context.Value(includeUnsetKey{}).(bool)
if ok && unset {
flag.VisitAll(visitFn)
} else {
flag.Visit(visitFn)
}
b, err := fs.opts.Encoder.Encode(changes)
if err != nil {
return nil, err
}
cs := &source.ChangeSet{
Format: fs.opts.Encoder.String(),
Data: b,
Timestamp: time.Now(),
Source: fs.String(),
}
cs.Checksum = cs.Sum()
return cs, nil
}
func split(r rune) bool {
return r == '-' || r == '_'
}
func reverse(ss []string) {
for i := len(ss)/2 - 1; i >= 0; i-- {
opp := len(ss) - 1 - i
ss[i], ss[opp] = ss[opp], ss[i]
}
}
func (fs *flagsrc) Watch() (source.Watcher, error) {
return source.NewNoopWatcher()
}
func (fs *flagsrc) Write(cs *source.ChangeSet) error {
return nil
}
func (fs *flagsrc) String() string {
return "flag"
}
// NewSource returns a config source for integrating parsed flags.
// Hyphens are delimiters for nesting, and all keys are lowercased.
//
// Example:
//
// dbhost := flag.String("database-host", "localhost", "the db host name")
//
// {
// "database": {
// "host": "localhost"
// }
// }
func NewSource(opts ...source.Option) source.Source {
return &flagsrc{opts: source.NewOptions(opts...)}
}