all: use Go 1.26 things, run most gofix modernizers

I omitted a lot of the min/max modernizers because they didn't
result in more clear code.

Some of it's older "for x := range 123".

Also: errors.AsType, any, fmt.Appendf, etc.

Updates #18682

Change-Id: I83a451577f33877f962766a5b65ce86f7696471c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2026-03-05 21:13:57 +00:00
committed by Brad Fitzpatrick
parent 4453cc5f53
commit bd2a2d53d3
168 changed files with 431 additions and 618 deletions
+3 -3
View File
@@ -102,12 +102,12 @@ func getSummarizeLearnedOutput(ri *appctype.RouteInfo) string {
}
return 0
})
s := ""
var s strings.Builder
fmtString := fmt.Sprintf("%%-%ds %%d\n", maxDomainWidth) // eg "%-10s %d\n"
for _, dc := range x {
s += fmt.Sprintf(fmtString, dc.domain, dc.count)
s.WriteString(fmt.Sprintf(fmtString, dc.domain, dc.count))
}
return s
return s.String()
}
func runAppcRoutesInfo(ctx context.Context, args []string) error {
+1 -1
View File
@@ -124,7 +124,7 @@ func Run(args []string) (err error) {
if errors.Is(err, flag.ErrHelp) {
return nil
}
if noexec := (ffcli.NoExecError{}); errors.As(err, &noexec) {
if noexec, ok := errors.AsType[ffcli.NoExecError](err); ok {
// When the user enters an unknown subcommand, ffcli tries to run
// the closest valid parent subcommand with everything else as args,
// returning NoExecError if it doesn't have an Exec function.
+2 -2
View File
@@ -962,8 +962,8 @@ func TestPrefFlagMapping(t *testing.T) {
}
prefType := reflect.TypeFor[ipn.Prefs]()
for i := range prefType.NumField() {
prefName := prefType.Field(i).Name
for field := range prefType.Fields() {
prefName := field.Name
if prefHasFlag[prefName] {
continue
}
+3 -5
View File
@@ -16,6 +16,7 @@ import (
"os/exec"
"path"
"runtime"
"slices"
"strings"
"github.com/peterbourgon/ff/v3/ffcli"
@@ -85,11 +86,8 @@ func runConfigureSynologyCert(ctx context.Context, args []string) error {
domain = st.CertDomains[0]
} else {
var found bool
for _, d := range st.CertDomains {
if d == domain {
found = true
break
}
if slices.Contains(st.CertDomains, domain) {
found = true
}
if !found {
return fmt.Errorf("Domain %q was not one of the valid domain options: %q.", domain, st.CertDomains)
+3 -4
View File
@@ -19,6 +19,7 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"sync"
"sync/atomic"
@@ -126,10 +127,8 @@ func runCp(ctx context.Context, args []string) error {
if cpArgs.name != "" {
return errors.New("can't use --name= with multiple files")
}
for _, fileArg := range files {
if fileArg == "-" {
return errors.New("can't use '-' as STDIN file when providing filename arguments")
}
if slices.Contains(files, "-") {
return errors.New("can't use '-' as STDIN file when providing filename arguments")
}
}
+5 -8
View File
@@ -9,6 +9,7 @@ import (
"flag"
"fmt"
"net/netip"
"slices"
"github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/ipn/ipnstate"
@@ -114,17 +115,13 @@ func peerMatchingIP(st *ipnstate.Status, ipStr string) (ps *ipnstate.PeerStatus,
return
}
for _, ps = range st.Peer {
for _, pip := range ps.TailscaleIPs {
if ip == pip {
return ps, true
}
if slices.Contains(ps.TailscaleIPs, ip) {
return ps, true
}
}
if ps := st.Self; ps != nil {
for _, pip := range ps.TailscaleIPs {
if ip == pip {
return ps, true
}
if slices.Contains(ps.TailscaleIPs, ip) {
return ps, true
}
}
return nil, false
+1 -1
View File
@@ -39,7 +39,7 @@ func registerAcceptRiskFlag(f *flag.FlagSet, acceptedRisks *string) {
// isRiskAccepted reports whether riskType is in the comma-separated list of
// risks in acceptedRisks.
func isRiskAccepted(riskType, acceptedRisks string) bool {
for _, r := range strings.Split(acceptedRisks, ",") {
for r := range strings.SplitSeq(acceptedRisks, ",") {
if r == riskType || r == riskAll {
return true
}
+2 -2
View File
@@ -114,8 +114,8 @@ func (u *acceptAppCapsFlag) Set(s string) error {
if s == "" {
return nil
}
appCaps := strings.Split(s, ",")
for _, appCap := range appCaps {
appCaps := strings.SplitSeq(s, ",")
for appCap := range appCaps {
appCap = strings.TrimSpace(appCap)
if !validAppCap.MatchString(appCap) {
return fmt.Errorf("%q does not match the form {domain}/{name}, where domain must be a fully qualified domain name", appCap)
+3 -4
View File
@@ -183,8 +183,7 @@ func runSet(ctx context.Context, args []string) (retErr error) {
maskedPrefs.AutoExitNode = expr
maskedPrefs.AutoExitNodeSet = true
} else if err := maskedPrefs.Prefs.SetExitNodeIP(setArgs.exitNodeIP, st); err != nil {
var e ipn.ExitNodeLocalIPError
if errors.As(err, &e) {
if _, ok := errors.AsType[ipn.ExitNodeLocalIPError](err); ok {
return fmt.Errorf("%w; did you mean --advertise-exit-node?", err)
}
return err
@@ -251,8 +250,8 @@ func runSet(ctx context.Context, args []string) (retErr error) {
if setArgs.relayServerStaticEndpoints != "" {
endpointsSet := make(set.Set[netip.AddrPort])
endpointsSplit := strings.Split(setArgs.relayServerStaticEndpoints, ",")
for _, s := range endpointsSplit {
endpointsSplit := strings.SplitSeq(setArgs.relayServerStaticEndpoints, ",")
for s := range endpointsSplit {
ap, err := netip.ParseAddrPort(s)
if err != nil {
return fmt.Errorf("failed to set relay server static endpoints: %q is not a valid IP:port", s)
+5 -8
View File
@@ -14,6 +14,7 @@ import (
"os/user"
"path/filepath"
"runtime"
"slices"
"strings"
"github.com/peterbourgon/ff/v3/ffcli"
@@ -202,10 +203,8 @@ func peerStatusFromArg(st *ipnstate.Status, arg string) (*ipnstate.PeerStatus, b
argIP, _ := netip.ParseAddr(arg)
for _, ps := range st.Peer {
if argIP.IsValid() {
for _, ip := range ps.TailscaleIPs {
if ip == argIP {
return ps, true
}
if slices.Contains(ps.TailscaleIPs, argIP) {
return ps, true
}
continue
}
@@ -230,10 +229,8 @@ func nodeDNSNameFromArg(st *ipnstate.Status, arg string) (dnsName string, ok boo
for _, ps := range st.Peer {
dnsName = ps.DNSName
if argIP.IsValid() {
for _, ip := range ps.TailscaleIPs {
if ip == argIP {
return dnsName, true
}
if slices.Contains(ps.TailscaleIPs, argIP) {
return dnsName, true
}
continue
}
+1 -2
View File
@@ -28,9 +28,8 @@ func execSSH(ssh string, argv []string) error {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
var ee *exec.ExitError
err := cmd.Run()
if errors.As(err, &ee) {
if ee, ok := errors.AsType[*exec.ExitError](err); ok {
os.Exit(ee.ExitCode())
}
return err
+1 -1
View File
@@ -39,7 +39,7 @@ func init() {
return ""
}
prefix := []byte("SSH_CLIENT=")
for _, env := range bytes.Split(b, []byte{0}) {
for env := range bytes.SplitSeq(b, []byte{0}) {
if bytes.HasPrefix(env, prefix) {
return string(env[len(prefix):])
}
+2 -3
View File
@@ -334,8 +334,7 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
if expr, useAutoExitNode := ipn.ParseAutoExitNodeString(upArgs.exitNodeIP); useAutoExitNode {
prefs.AutoExitNode = expr
} else if err := prefs.SetExitNodeIP(upArgs.exitNodeIP, st); err != nil {
var e ipn.ExitNodeLocalIPError
if errors.As(err, &e) {
if _, ok := errors.AsType[ipn.ExitNodeLocalIPError](err); ok {
return nil, fmt.Errorf("%w; did you mean --advertise-exit-node?", err)
}
return nil, err
@@ -912,7 +911,7 @@ func addPrefFlagMapping(flagName string, prefNames ...string) {
prefType := reflect.TypeFor[ipn.Prefs]()
for _, pref := range prefNames {
t := prefType
for _, name := range strings.Split(pref, ".") {
for name := range strings.SplitSeq(pref, ".") {
// Crash at runtime if there's a typo in the prefName.
f, ok := t.FieldByName(name)
if !ok {