go cmd/doc: garbled -src output

fkaflof6  于 6个月前  发布在  Go
关注(0)|答案(1)|浏览(42)

你正在使用的Go版本是什么(go version)?

$ go version
go version go1.13.7 linux/amd64

这个问题在最新版本的发布中是否会重现?

是的(go1.13.7是最新版本)。

你正在使用什么操作系统和处理器架构(go env)?

go env 输出

$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/tv/.cache/go-build"
GOENV="/home/tv/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=[censored, not related]
GONOSUMDB=[censored, not related]
GOOS="linux"
GOPATH="/home/tv/go"
GOPRIVATE=[censored, not related]
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/tv/sdk/go1.13.7"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/tv/sdk/go1.13.7/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/tv/go/src/eagain.net/go/securityblanket/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/home/tv/tmp/go-build488236536=/tmp/go-build -gno-record-gcc-switches"

你做了什么?

在一个没有直接使用xerrors的模块中,github.com/google/go-cmp v0.4.0引入了golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543:

$ go doc -src xerrors.As
package xerrors // import "golang.org/x/xerrors"

// As finds the first error in err's chain that matches the type to which target
// points, and if so, sets the target to its value and returns true. An error
// matches a type if it is assignable to the target type, or if it has a method
// As(interface{}) bool such that As(target) returns true. As will panic if target
// is not a non-nil pointer to a type which implements error or is of interface type.
//
// The As method should set the target to its value and return true if err
// matches the type to which target points.

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// FormatError calls the FormatError method of f with an errors.Printer
// configured according to s and verb, and writes the result to s.

// Assuming this function is only called from the Format method, and given
// that FormatError takes precedence over Format, it cannot be called from
// any package that supports errors.Formatter. It is therefore safe to
// disregard that State may be a specific printer implementation and use one
// of our choice instead.

// limitations: does not support printing error as Go struct.

// separator before next error

// Note that this switch must match the preference order
// for ordinary string printing (%#v before %+v, and so on).

// proceed as if it were %v

// Use an intermediate buffer in the rare cases that precision,
// truncation, or one of the alternative verbs (q, x, and X) are
// specified.

func As(err error,

// Construct format string from State s.
target interface{}) bool {
	if target == nil {
		panic("errors: target cannot be nil")
	}
	val := reflect.ValueOf(target)
	typ := val.Type()
	if typ.Kind() != reflect.Ptr || val.IsNil() {
		panic("errors: target must be a non-nil pointer")
	}
	if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) {
		panic("errors: *target must be interface or implement error")
	}
	targetType := typ.Elem()
	for err != nil {
		if reflect.TypeOf(err).AssignableTo(targetType) {
			val.Elem().Set(reflect.ValueOf(err))
			return true
		}
		if x, ok :=

		// state tracks error printing state. It implements fmt.State.
		err.(interface{ As(interface{}) bool }); ok && x.As(target) {
			return true
		}
		err = Unwrap(err)
	}
	return false
}

// printer wraps a state to implement an xerrors.Printer.

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package xerrors implements functions to manipulate errors.
//
// This package is based on the Go 2 proposal for error values:
//   https://golang.org/design/29934-error-values
//
// These functions were incorporated into the standard library's errors package
// in Go 1.13:
// - Is
// - As
// - Unwrap
//
// Also, Errorf's %w verb was incorporated into fmt.Errorf.
//
// Use this package to get equivalent behavior in all supported Go versions.
//
// No other features of this package were included in Go 1.13, and at present
// there are no plans to include any of them.
// import "golang.org/x/xerrors"

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// errorString is a trivial implementation of error.

// New returns an error that formats as the given text.
//
// The returned error contains a Frame set to the caller's location and
// implements Formatter to show this information when printed with details.

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
// The returned error includes the file and line number of the caller when
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
// format string ends with ": %w", the returned error implements an Unwrap
// method returning it.
//
// If the format specifier includes a %w verb with an error operand in a
// position other than at the end, the returned error will still implement an
// Unwrap method returning the operand, but the error's Format method will not
// return the wrapped error.
//
// It is invalid to include more than one %w verb or to supply it with an
// operand that does not implement the error interface. The %w verb is otherwise
// a synonym for %v.

// Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.

// TODO: this is not entirely correct. The error value could be
// printed elsewhere in format if it mixes numbered with unnumbered
// substitutions. With relatively small changes to doPrintf we can
// have it optionally ignore extra arguments and pass the argument
// list in its entirety.

// Support %w anywhere.
// TODO: don't repeat the wrapped error's message when %w occurs in the middle.

// Too many %ws or argument of %w is not an error. Approximate the Go
// 1.13 fmt.Errorf message.

// formatPlusW is used to avoid the vet check that will barf at %w.

// Return the index of the only %w in format, or -1 if none.
// Also return a rewritten format string with %w replaced by %v, and
// false if there is more than one %w.
// TODO: handle "%[N]w".

// Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.

// "%%" is not a format directive.

// "Replace" the last character, the 'w', with a 'v'.

// Parse the printf verb starting with a % at s[0].
// Return how many bytes it occupies and whether the verb is 'w'.

// Assume only that the directive is a sequence of non-letters followed by a single letter.

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// A Formatter formats error messages.

// FormatError prints the receiver's first error and returns the next error in
// the error chain, if any.

// A Printer formats error messages.
//
// The most common implementation of Printer is the one provided by package fmt
// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message
// typically provide their own implementations.

// Print appends args to the message output.

// Printf writes a formatted string.

// Detail reports whether error detail is requested.
// After the first call to Detail, all text written to the Printer
// is formatted as additional detail, or ignored when
// detail has not been requested.
// If Detail returns false, the caller can avoid printing the detail at all.

再次运行:

$ go doc -src xerrors.As
package xerrors // import "golang.org/x/xerrors"

// As finds the first error in err's chain that matches the type to which target
// points, and if so, sets the target to its value and returns true. An error
// matches a type if it is assignable to the target type, or if it has a method
// As(interface{}) bool such that As(target) returns true. As will panic if target
// is not a non-nil pointer to a type which implements error or is of interface type.
//
// The As method should set the target to its value and return true if err
// matches the type to which target points.
func As(err error, target interface{}) bool {
	if target == nil {
		panic("errors: target cannot be nil")
	}
	val := reflect.ValueOf(target)
	typ := val.Type()
	if typ.Kind() != reflect.Ptr || val.IsNil() {
		panic("errors: target must be a non-nil pointer")
	}
	if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) {
		panic("errors: *target must be interface or implement error")
	}
	targetType := typ.Elem()
	for err != nil {
		if reflect.TypeOf(err).AssignableTo(targetType) {
			val.Elem().Set(reflect.ValueOf(err))
			return true
		}
		if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) {
			return true
		}
		err = Unwrap(err)
	}
	return false
}
$

杂乱的输出大约出现了50%的时间。

你期望看到什么?

仅As函数的函数注解和主体。

你看到了什么?

似乎将两个源流组合在一起的输出。

mwyxok5s

mwyxok5s1#

看起来又发生了同样的事情,在crawshaw.io/sqlite/sqlitex中:

$ go doc -src sqlitex.Pool.GetSnapshot
package sqlitex // import "crawshaw.io/sqlite/sqlitex"

// GetSnapshot returns a Snapshot that should remain available for reads until
// it is garbage collected.
//
// This sets aside a Conn from the Pool with an open read transaction until the
// Snapshot is garbage collected or the Pool is closed.  Thus, until the
// returned Snapshot is garbage collected, the Pool will have one fewer Conn,
// and it should not be possible for the WAL to be checkpointed beyond the
// point of the Snapshot.
//
// See sqlite.Conn.GetSnapshot and sqlite.Snapshot for more details.
func (p *Pool) GetSnapshot(ctx context.Context, schema string) (*sqlite.Snapshot, error) {
	conn := p.Get(ctx)
	if conn == nil {
		return nil, context.Canceled
	}
	conn.SetInterrupt(nil)
	s, release, err := conn.GetSnapshot(schema)
	if err != nil {
		return nil, err
	}

	snapshotGCd := make(chan struct{})
	runtime.SetFinalizer(s, nil)
	runtime.SetFinalizer(s, func(s *sqlite.Snapshot) {
		// Free the C resources associated with the Snapshot.
		s.Free()
		close(snapshotGCd)
	})

	go func() {
		select {
		case <-p.closed:
		case <-snapshotGCd:
		}
		// Allow the WAL to be checkpointed past the point of
		// the Snapshot.
		release()
		// Return the conn to the Pool for reuse.

		// Copyright (c) 2018 David Crawshaw <david@zentus.com>
		//
		// Permission to use, copy, modify, and distribute this software for any
		// purpose with or without fee is hereby granted, provided that the above
		// copyright notice and this permission notice appear in all copies.
		//
		// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
		// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
		// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
		// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
		// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
		// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
		// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

		// A Buffer is a variable-sized bytes buffer backed by SQLite blobs.
		//
		// The bytes are broken into pages, with the first and last pages
		// stored in memory, and intermediate pages loaded into blobs.
		// Unlike a single SQLite blob, a Buffer can grow beyond its initial size.
		// The blobs are allocated in a temporary table.
		//
		// A Buffer is very similar to a bytes.Buffer.

		p.Put(conn)
	}()

	return s, nil
}

// cap(rbuf) == cap(wbuf) == blobs[N].Size()

// read buffer
// read head position in roff
// blobs storing data between rbuf and wbuf
// write buffer

// NewBuffer creates a Buffer with 16KB pages.

// NewBufferSize creates a Buffer with a specified page size.

// Flush the write buffer.

// Short cut. The write buffer is full, but
// there are no on-disk blobs and the read
// buffer is empty. So push these bytes
// directly to the front of the Buffer.

// WriteByte appends a byte to the buffer, growing it as needed.

// TODO: shortcut for writing large p directly into a new blob

// never grows wbuf

// TODO: shortcut for writing large p directly into a new blob

// never grows wbuf

// Read buffer is empty. Fill it.

// Read the first blob entirely into the read buffer.
// TODO: shortcut for if len(p) >= blob.Size()

// No blobs. Swap the write buffer bytes here directly.

许可证文本和尾随注解不是函数的一部分。

相关问题