github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/os/exec/exec.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package exec runs external commands. It wraps os.StartProcess to make it 6 // easier to remap stdin and stdout, connect I/O with pipes, and do other 7 // adjustments. 8 // 9 // Unlike the "system" library call from C and other languages, the 10 // os/exec package intentionally does not invoke the system shell and 11 // does not expand any glob patterns or handle other expansions, 12 // pipelines, or redirections typically done by shells. The package 13 // behaves more like C's "exec" family of functions. To expand glob 14 // patterns, either call the shell directly, taking care to escape any 15 // dangerous input, or use the path/filepath package's Glob function. 16 // To expand environment variables, use package os's ExpandEnv. 17 // 18 // Note that the examples in this package assume a Unix system. 19 // They may not run on Windows, and they do not run in the Go Playground 20 // used by golang.org and godoc.org. 21 package exec 22 23 import ( 24 "bytes" 25 "context" 26 "errors" 27 "io" 28 "os" 29 "path/filepath" 30 "runtime" 31 "strconv" 32 "strings" 33 "sync" 34 "syscall" 35 ) 36 37 // Error records the name of a binary that failed to be executed 38 // and the reason it failed. 39 type Error struct { 40 Name string 41 Err error 42 } 43 44 func (e *Error) Error() string { 45 return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error() 46 } 47 48 // Cmd represents an external command being prepared or run. 49 // 50 // A Cmd cannot be reused after calling its Run, Output or CombinedOutput 51 // methods. 52 type Cmd struct { 53 // Path is the path of the command to run. 54 // 55 // This is the only field that must be set to a non-zero 56 // value. If Path is relative, it is evaluated relative 57 // to Dir. 58 Path string 59 60 // Args holds command line arguments, including the command as Args[0]. 61 // If the Args field is empty or nil, Run uses {Path}. 62 // 63 // In typical use, both Path and Args are set by calling Command. 64 Args []string 65 66 // Env specifies the environment of the process. 67 // Each entry is of the form "key=value". 68 // If Env is nil, the new process uses the current process's 69 // environment. 70 // If Env contains duplicate environment keys, only the last 71 // value in the slice for each duplicate key is used. 72 Env []string 73 74 // Dir specifies the working directory of the command. 75 // If Dir is the empty string, Run runs the command in the 76 // calling process's current directory. 77 Dir string 78 79 // Stdin specifies the process's standard input. 80 // If Stdin is nil, the process reads from the null device (os.DevNull). 81 // If Stdin is an *os.File, the process's standard input is connected 82 // directly to that file. 83 // Otherwise, during the execution of the command a separate 84 // goroutine reads from Stdin and delivers that data to the command 85 // over a pipe. In this case, Wait does not complete until the goroutine 86 // stops copying, either because it has reached the end of Stdin 87 // (EOF or a read error) or because writing to the pipe returned an error. 88 Stdin io.Reader 89 90 // Stdout and Stderr specify the process's standard output and error. 91 // 92 // If either is nil, Run connects the corresponding file descriptor 93 // to the null device (os.DevNull). 94 // 95 // If Stdout and Stderr are the same writer, and have a type that can be compared with ==, 96 // at most one goroutine at a time will call Write. 97 Stdout io.Writer 98 Stderr io.Writer 99 100 // ExtraFiles specifies additional open files to be inherited by the 101 // new process. It does not include standard input, standard output, or 102 // standard error. If non-nil, entry i becomes file descriptor 3+i. 103 ExtraFiles []*os.File 104 105 // SysProcAttr holds optional, operating system-specific attributes. 106 // Run passes it to os.StartProcess as the os.ProcAttr's Sys field. 107 SysProcAttr *syscall.SysProcAttr 108 109 // Process is the underlying process, once started. 110 Process *os.Process 111 112 // ProcessState contains information about an exited process, 113 // available after a call to Wait or Run. 114 ProcessState *os.ProcessState 115 116 ctx context.Context // nil means none 117 lookPathErr error // LookPath error, if any. 118 finished bool // when Wait was called 119 childFiles []*os.File 120 closeAfterStart []io.Closer 121 closeAfterWait []io.Closer 122 goroutine []func() error 123 errch chan error // one send per goroutine 124 waitDone chan struct{} 125 } 126 127 // Command returns the Cmd struct to execute the named program with 128 // the given arguments. 129 // 130 // It sets only the Path and Args in the returned structure. 131 // 132 // If name contains no path separators, Command uses LookPath to 133 // resolve name to a complete path if possible. Otherwise it uses name 134 // directly as Path. 135 // 136 // The returned Cmd's Args field is constructed from the command name 137 // followed by the elements of arg, so arg should not include the 138 // command name itself. For example, Command("echo", "hello"). 139 // Args[0] is always name, not the possibly resolved Path. 140 func Command(name string, arg ...string) *Cmd { 141 cmd := &Cmd{ 142 Path: name, 143 Args: append([]string{name}, arg...), 144 } 145 if filepath.Base(name) == name { 146 if lp, err := LookPath(name); err != nil { 147 cmd.lookPathErr = err 148 } else { 149 cmd.Path = lp 150 } 151 } 152 return cmd 153 } 154 155 // CommandContext is like Command but includes a context. 156 // 157 // The provided context is used to kill the process (by calling 158 // os.Process.Kill) if the context becomes done before the command 159 // completes on its own. 160 func CommandContext(ctx context.Context, name string, arg ...string) *Cmd { 161 if ctx == nil { 162 panic("nil Context") 163 } 164 cmd := Command(name, arg...) 165 cmd.ctx = ctx 166 return cmd 167 } 168 169 // interfaceEqual protects against panics from doing equality tests on 170 // two interfaces with non-comparable underlying types. 171 func interfaceEqual(a, b interface{}) bool { 172 defer func() { 173 recover() 174 }() 175 return a == b 176 } 177 178 func (c *Cmd) envv() []string { 179 if c.Env != nil { 180 return c.Env 181 } 182 return os.Environ() 183 } 184 185 func (c *Cmd) argv() []string { 186 if len(c.Args) > 0 { 187 return c.Args 188 } 189 return []string{c.Path} 190 } 191 192 // skipStdinCopyError optionally specifies a function which reports 193 // whether the provided the stdin copy error should be ignored. 194 // It is non-nil everywhere but Plan 9, which lacks EPIPE. See exec_posix.go. 195 var skipStdinCopyError func(error) bool 196 197 func (c *Cmd) stdin() (f *os.File, err error) { 198 if c.Stdin == nil { 199 f, err = os.Open(os.DevNull) 200 if err != nil { 201 return 202 } 203 c.closeAfterStart = append(c.closeAfterStart, f) 204 return 205 } 206 207 if f, ok := c.Stdin.(*os.File); ok { 208 return f, nil 209 } 210 211 pr, pw, err := os.Pipe() 212 if err != nil { 213 return 214 } 215 216 c.closeAfterStart = append(c.closeAfterStart, pr) 217 c.closeAfterWait = append(c.closeAfterWait, pw) 218 c.goroutine = append(c.goroutine, func() error { 219 _, err := io.Copy(pw, c.Stdin) 220 if skip := skipStdinCopyError; skip != nil && skip(err) { 221 err = nil 222 } 223 if err1 := pw.Close(); err == nil { 224 err = err1 225 } 226 return err 227 }) 228 return pr, nil 229 } 230 231 func (c *Cmd) stdout() (f *os.File, err error) { 232 return c.writerDescriptor(c.Stdout) 233 } 234 235 func (c *Cmd) stderr() (f *os.File, err error) { 236 if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) { 237 return c.childFiles[1], nil 238 } 239 return c.writerDescriptor(c.Stderr) 240 } 241 242 func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) { 243 if w == nil { 244 f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0) 245 if err != nil { 246 return 247 } 248 c.closeAfterStart = append(c.closeAfterStart, f) 249 return 250 } 251 252 if f, ok := w.(*os.File); ok { 253 return f, nil 254 } 255 256 pr, pw, err := os.Pipe() 257 if err != nil { 258 return 259 } 260 261 c.closeAfterStart = append(c.closeAfterStart, pw) 262 c.closeAfterWait = append(c.closeAfterWait, pr) 263 c.goroutine = append(c.goroutine, func() error { 264 _, err := io.Copy(w, pr) 265 pr.Close() // in case io.Copy stopped due to write error 266 return err 267 }) 268 return pw, nil 269 } 270 271 func (c *Cmd) closeDescriptors(closers []io.Closer) { 272 for _, fd := range closers { 273 fd.Close() 274 } 275 } 276 277 // Run starts the specified command and waits for it to complete. 278 // 279 // The returned error is nil if the command runs, has no problems 280 // copying stdin, stdout, and stderr, and exits with a zero exit 281 // status. 282 // 283 // If the command starts but does not complete successfully, the error is of 284 // type *ExitError. Other error types may be returned for other situations. 285 func (c *Cmd) Run() error { 286 if err := c.Start(); err != nil { 287 return err 288 } 289 return c.Wait() 290 } 291 292 // lookExtensions finds windows executable by its dir and path. 293 // It uses LookPath to try appropriate extensions. 294 // lookExtensions does not search PATH, instead it converts `prog` into `.\prog`. 295 func lookExtensions(path, dir string) (string, error) { 296 if filepath.Base(path) == path { 297 path = filepath.Join(".", path) 298 } 299 if dir == "" { 300 return LookPath(path) 301 } 302 if filepath.VolumeName(path) != "" { 303 return LookPath(path) 304 } 305 if len(path) > 1 && os.IsPathSeparator(path[0]) { 306 return LookPath(path) 307 } 308 dirandpath := filepath.Join(dir, path) 309 // We assume that LookPath will only add file extension. 310 lp, err := LookPath(dirandpath) 311 if err != nil { 312 return "", err 313 } 314 ext := strings.TrimPrefix(lp, dirandpath) 315 return path + ext, nil 316 } 317 318 // Start starts the specified command but does not wait for it to complete. 319 // 320 // The Wait method will return the exit code and release associated resources 321 // once the command exits. 322 func (c *Cmd) Start() error { 323 if c.lookPathErr != nil { 324 c.closeDescriptors(c.closeAfterStart) 325 c.closeDescriptors(c.closeAfterWait) 326 return c.lookPathErr 327 } 328 if runtime.GOOS == "windows" { 329 lp, err := lookExtensions(c.Path, c.Dir) 330 if err != nil { 331 c.closeDescriptors(c.closeAfterStart) 332 c.closeDescriptors(c.closeAfterWait) 333 return err 334 } 335 c.Path = lp 336 } 337 if c.Process != nil { 338 return errors.New("exec: already started") 339 } 340 if c.ctx != nil { 341 select { 342 case <-c.ctx.Done(): 343 c.closeDescriptors(c.closeAfterStart) 344 c.closeDescriptors(c.closeAfterWait) 345 return c.ctx.Err() 346 default: 347 } 348 } 349 350 type F func(*Cmd) (*os.File, error) 351 for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { 352 fd, err := setupFd(c) 353 if err != nil { 354 c.closeDescriptors(c.closeAfterStart) 355 c.closeDescriptors(c.closeAfterWait) 356 return err 357 } 358 c.childFiles = append(c.childFiles, fd) 359 } 360 c.childFiles = append(c.childFiles, c.ExtraFiles...) 361 362 var err error 363 c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ 364 Dir: c.Dir, 365 Files: c.childFiles, 366 Env: dedupEnv(c.envv()), 367 Sys: c.SysProcAttr, 368 }) 369 if err != nil { 370 c.closeDescriptors(c.closeAfterStart) 371 c.closeDescriptors(c.closeAfterWait) 372 return err 373 } 374 375 c.closeDescriptors(c.closeAfterStart) 376 377 c.errch = make(chan error, len(c.goroutine)) 378 for _, fn := range c.goroutine { 379 go func(fn func() error) { 380 c.errch <- fn() 381 }(fn) 382 } 383 384 if c.ctx != nil { 385 c.waitDone = make(chan struct{}) 386 go func() { 387 select { 388 case <-c.ctx.Done(): 389 c.Process.Kill() 390 case <-c.waitDone: 391 } 392 }() 393 } 394 395 return nil 396 } 397 398 // An ExitError reports an unsuccessful exit by a command. 399 type ExitError struct { 400 *os.ProcessState 401 402 // Stderr holds a subset of the standard error output from the 403 // Cmd.Output method if standard error was not otherwise being 404 // collected. 405 // 406 // If the error output is long, Stderr may contain only a prefix 407 // and suffix of the output, with the middle replaced with 408 // text about the number of omitted bytes. 409 // 410 // Stderr is provided for debugging, for inclusion in error messages. 411 // Users with other needs should redirect Cmd.Stderr as needed. 412 Stderr []byte 413 } 414 415 func (e *ExitError) Error() string { 416 return e.ProcessState.String() 417 } 418 419 // Wait waits for the command to exit and waits for any copying to 420 // stdin or copying from stdout or stderr to complete. 421 // 422 // The command must have been started by Start. 423 // 424 // The returned error is nil if the command runs, has no problems 425 // copying stdin, stdout, and stderr, and exits with a zero exit 426 // status. 427 // 428 // If the command fails to run or doesn't complete successfully, the 429 // error is of type *ExitError. Other error types may be 430 // returned for I/O problems. 431 // 432 // If c.Stdin is not an *os.File, Wait also waits for the I/O loop 433 // copying from c.Stdin into the process's standard input 434 // to complete. 435 // 436 // Wait releases any resources associated with the Cmd. 437 func (c *Cmd) Wait() error { 438 if c.Process == nil { 439 return errors.New("exec: not started") 440 } 441 if c.finished { 442 return errors.New("exec: Wait was already called") 443 } 444 c.finished = true 445 446 state, err := c.Process.Wait() 447 if c.waitDone != nil { 448 close(c.waitDone) 449 } 450 c.ProcessState = state 451 452 var copyError error 453 for range c.goroutine { 454 if err := <-c.errch; err != nil && copyError == nil { 455 copyError = err 456 } 457 } 458 459 c.closeDescriptors(c.closeAfterWait) 460 461 if err != nil { 462 return err 463 } else if !state.Success() { 464 return &ExitError{ProcessState: state} 465 } 466 467 return copyError 468 } 469 470 // Output runs the command and returns its standard output. 471 // Any returned error will usually be of type *ExitError. 472 // If c.Stderr was nil, Output populates ExitError.Stderr. 473 func (c *Cmd) Output() ([]byte, error) { 474 if c.Stdout != nil { 475 return nil, errors.New("exec: Stdout already set") 476 } 477 var stdout bytes.Buffer 478 c.Stdout = &stdout 479 480 captureErr := c.Stderr == nil 481 if captureErr { 482 c.Stderr = &prefixSuffixSaver{N: 32 << 10} 483 } 484 485 err := c.Run() 486 if err != nil && captureErr { 487 if ee, ok := err.(*ExitError); ok { 488 ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes() 489 } 490 } 491 return stdout.Bytes(), err 492 } 493 494 // CombinedOutput runs the command and returns its combined standard 495 // output and standard error. 496 func (c *Cmd) CombinedOutput() ([]byte, error) { 497 if c.Stdout != nil { 498 return nil, errors.New("exec: Stdout already set") 499 } 500 if c.Stderr != nil { 501 return nil, errors.New("exec: Stderr already set") 502 } 503 var b bytes.Buffer 504 c.Stdout = &b 505 c.Stderr = &b 506 err := c.Run() 507 return b.Bytes(), err 508 } 509 510 // StdinPipe returns a pipe that will be connected to the command's 511 // standard input when the command starts. 512 // The pipe will be closed automatically after Wait sees the command exit. 513 // A caller need only call Close to force the pipe to close sooner. 514 // For example, if the command being run will not exit until standard input 515 // is closed, the caller must close the pipe. 516 func (c *Cmd) StdinPipe() (io.WriteCloser, error) { 517 if c.Stdin != nil { 518 return nil, errors.New("exec: Stdin already set") 519 } 520 if c.Process != nil { 521 return nil, errors.New("exec: StdinPipe after process started") 522 } 523 pr, pw, err := os.Pipe() 524 if err != nil { 525 return nil, err 526 } 527 c.Stdin = pr 528 c.closeAfterStart = append(c.closeAfterStart, pr) 529 wc := &closeOnce{File: pw} 530 c.closeAfterWait = append(c.closeAfterWait, closerFunc(wc.safeClose)) 531 return wc, nil 532 } 533 534 type closeOnce struct { 535 *os.File 536 537 writers sync.RWMutex // coordinate safeClose and Write 538 once sync.Once 539 err error 540 } 541 542 func (c *closeOnce) Close() error { 543 c.once.Do(c.close) 544 return c.err 545 } 546 547 func (c *closeOnce) close() { 548 c.err = c.File.Close() 549 } 550 551 type closerFunc func() error 552 553 func (f closerFunc) Close() error { return f() } 554 555 // safeClose closes c being careful not to race with any calls to c.Write. 556 // See golang.org/issue/9307 and TestEchoFileRace in exec_test.go. 557 // In theory other calls could also be excluded (by writing appropriate 558 // wrappers like c.Write's implementation below), but since c is most 559 // commonly used as a WriteCloser, Write is the main one to worry about. 560 // See also #7970, for which this is a partial fix for this specific instance. 561 // The idea is that we return a WriteCloser, and so the caller can be 562 // relied upon not to call Write and Close simultaneously, but it's less 563 // obvious that cmd.Wait calls Close and that the caller must not call 564 // Write and cmd.Wait simultaneously. In fact that seems too onerous. 565 // So we change the use of Close in cmd.Wait to use safeClose, which will 566 // synchronize with any Write. 567 // 568 // It's important that we know this won't block forever waiting for the 569 // operations being excluded. At the point where this is called, 570 // the invoked command has exited and the parent copy of the read side 571 // of the pipe has also been closed, so there should really be no read side 572 // of the pipe left. Any active writes should return very shortly with an EPIPE, 573 // making it reasonable to wait for them. 574 // Technically it is possible that the child forked a sub-process or otherwise 575 // handed off the read side of the pipe before exiting and the current holder 576 // is not reading from the pipe, and the pipe is full, in which case the close here 577 // might block waiting for the write to complete. That's probably OK. 578 // It's a small enough problem to be outweighed by eliminating the race here. 579 func (c *closeOnce) safeClose() error { 580 c.writers.Lock() 581 err := c.Close() 582 c.writers.Unlock() 583 return err 584 } 585 586 func (c *closeOnce) Write(b []byte) (int, error) { 587 c.writers.RLock() 588 n, err := c.File.Write(b) 589 c.writers.RUnlock() 590 return n, err 591 } 592 593 func (c *closeOnce) WriteString(s string) (int, error) { 594 c.writers.RLock() 595 n, err := c.File.WriteString(s) 596 c.writers.RUnlock() 597 return n, err 598 } 599 600 // StdoutPipe returns a pipe that will be connected to the command's 601 // standard output when the command starts. 602 // 603 // Wait will close the pipe after seeing the command exit, so most callers 604 // need not close the pipe themselves; however, an implication is that 605 // it is incorrect to call Wait before all reads from the pipe have completed. 606 // For the same reason, it is incorrect to call Run when using StdoutPipe. 607 // See the example for idiomatic usage. 608 func (c *Cmd) StdoutPipe() (io.ReadCloser, error) { 609 if c.Stdout != nil { 610 return nil, errors.New("exec: Stdout already set") 611 } 612 if c.Process != nil { 613 return nil, errors.New("exec: StdoutPipe after process started") 614 } 615 pr, pw, err := os.Pipe() 616 if err != nil { 617 return nil, err 618 } 619 c.Stdout = pw 620 c.closeAfterStart = append(c.closeAfterStart, pw) 621 c.closeAfterWait = append(c.closeAfterWait, pr) 622 return pr, nil 623 } 624 625 // StderrPipe returns a pipe that will be connected to the command's 626 // standard error when the command starts. 627 // 628 // Wait will close the pipe after seeing the command exit, so most callers 629 // need not close the pipe themselves; however, an implication is that 630 // it is incorrect to call Wait before all reads from the pipe have completed. 631 // For the same reason, it is incorrect to use Run when using StderrPipe. 632 // See the StdoutPipe example for idiomatic usage. 633 func (c *Cmd) StderrPipe() (io.ReadCloser, error) { 634 if c.Stderr != nil { 635 return nil, errors.New("exec: Stderr already set") 636 } 637 if c.Process != nil { 638 return nil, errors.New("exec: StderrPipe after process started") 639 } 640 pr, pw, err := os.Pipe() 641 if err != nil { 642 return nil, err 643 } 644 c.Stderr = pw 645 c.closeAfterStart = append(c.closeAfterStart, pw) 646 c.closeAfterWait = append(c.closeAfterWait, pr) 647 return pr, nil 648 } 649 650 // prefixSuffixSaver is an io.Writer which retains the first N bytes 651 // and the last N bytes written to it. The Bytes() methods reconstructs 652 // it with a pretty error message. 653 type prefixSuffixSaver struct { 654 N int // max size of prefix or suffix 655 prefix []byte 656 suffix []byte // ring buffer once len(suffix) == N 657 suffixOff int // offset to write into suffix 658 skipped int64 659 660 // TODO(bradfitz): we could keep one large []byte and use part of it for 661 // the prefix, reserve space for the '... Omitting N bytes ...' message, 662 // then the ring buffer suffix, and just rearrange the ring buffer 663 // suffix when Bytes() is called, but it doesn't seem worth it for 664 // now just for error messages. It's only ~64KB anyway. 665 } 666 667 func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) { 668 lenp := len(p) 669 p = w.fill(&w.prefix, p) 670 671 // Only keep the last w.N bytes of suffix data. 672 if overage := len(p) - w.N; overage > 0 { 673 p = p[overage:] 674 w.skipped += int64(overage) 675 } 676 p = w.fill(&w.suffix, p) 677 678 // w.suffix is full now if p is non-empty. Overwrite it in a circle. 679 for len(p) > 0 { // 0, 1, or 2 iterations. 680 n := copy(w.suffix[w.suffixOff:], p) 681 p = p[n:] 682 w.skipped += int64(n) 683 w.suffixOff += n 684 if w.suffixOff == w.N { 685 w.suffixOff = 0 686 } 687 } 688 return lenp, nil 689 } 690 691 // fill appends up to len(p) bytes of p to *dst, such that *dst does not 692 // grow larger than w.N. It returns the un-appended suffix of p. 693 func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) { 694 if remain := w.N - len(*dst); remain > 0 { 695 add := minInt(len(p), remain) 696 *dst = append(*dst, p[:add]...) 697 p = p[add:] 698 } 699 return p 700 } 701 702 func (w *prefixSuffixSaver) Bytes() []byte { 703 if w.suffix == nil { 704 return w.prefix 705 } 706 if w.skipped == 0 { 707 return append(w.prefix, w.suffix...) 708 } 709 var buf bytes.Buffer 710 buf.Grow(len(w.prefix) + len(w.suffix) + 50) 711 buf.Write(w.prefix) 712 buf.WriteString("\n... omitting ") 713 buf.WriteString(strconv.FormatInt(w.skipped, 10)) 714 buf.WriteString(" bytes ...\n") 715 buf.Write(w.suffix[w.suffixOff:]) 716 buf.Write(w.suffix[:w.suffixOff]) 717 return buf.Bytes() 718 } 719 720 func minInt(a, b int) int { 721 if a < b { 722 return a 723 } 724 return b 725 } 726 727 // dedupEnv returns a copy of env with any duplicates removed, in favor of 728 // later values. 729 // Items not of the normal environment "key=value" form are preserved unchanged. 730 func dedupEnv(env []string) []string { 731 return dedupEnvCase(runtime.GOOS == "windows", env) 732 } 733 734 // dedupEnvCase is dedupEnv with a case option for testing. 735 // If caseInsensitive is true, the case of keys is ignored. 736 func dedupEnvCase(caseInsensitive bool, env []string) []string { 737 out := make([]string, 0, len(env)) 738 saw := map[string]int{} // key => index into out 739 for _, kv := range env { 740 eq := strings.Index(kv, "=") 741 if eq < 0 { 742 out = append(out, kv) 743 continue 744 } 745 k := kv[:eq] 746 if caseInsensitive { 747 k = strings.ToLower(k) 748 } 749 if dupIdx, isDup := saw[k]; isDup { 750 out[dupIdx] = kv 751 continue 752 } 753 saw[k] = len(out) 754 out = append(out, kv) 755 } 756 return out 757 }