项目文件夹

文件
Asim Aslam 4311b73361 Enhance ADK vs Go Micro comparison and apply lint fixes (#2994)
* docs: compare Go Micro with Google ADK in the comparison guide

Adds a 'vs Agent Frameworks (Google ADK)' section: ADK builds an agent,
Go Micro builds the distributed system the agent lives in (agents are
services in the mesh). Covers the category difference, a feature table,
when to choose each, and MCP/A2A interoperability.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

* docs: replace ADK comparison slogan with concrete explanation

State plainly what each tool provides (ADK builds an agent process; Go Micro
builds the surrounding service mesh) instead of marketing phrasing.

* lint: apply golangci-lint autofixes; exclude ST1003 and demo errcheck

Mechanical, behaviour-preserving fixes applied by 'golangci-lint run --fix':
gofmt, misspell (US spelling), usestdlibvars (http.Method*/Status*), unconvert,
and the auto-fixable staticcheck simplifications (QF*, S1017/S1019/S1023/S1039).

Config: exclude ST1003 (remaining offenders are exported API renames, e.g.
web.Id, which would break compatibility) and skip errcheck for examples/ and
internal/harness/ (demo code where fire-and-forget is intentional).

Build and test compilation verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

* lint: WIP cleanup checkpoint (errcheck config + partial fixes)

Checkpoint of an in-progress golangci-lint cleanup (background pass). Builds
cleanly; lint is not yet zero. Follow-up commit will complete the cleanup and
switch CI to a blocking full-tree lint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmdEY7pYmV5zzwCjNJ4ykL

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 17:21:47 +01:00

217 行
3.3 KiB
Go

package transport
import (
"bufio"
"bytes"
"io"
"net"
"net/http"
"net/url"
"sync"
"time"
"github.com/pkg/errors"
"go-micro.dev/v6/internal/util/buf"
log "go-micro.dev/v6/logger"
)
type httpTransportClient struct {
dialOpts DialOptions
conn net.Conn
ht *httpTransport
// request must be stored for response processing
req chan *http.Request
buff *bufio.Reader
addr string
// local/remote ip
local string
remote string
reqList []*http.Request
sync.RWMutex
once sync.Once
closed bool
}
func (h *httpTransportClient) Local() string {
return h.local
}
func (h *httpTransportClient) Remote() string {
return h.remote
}
func (h *httpTransportClient) Send(m *Message) error {
logger := h.ht.Options().Logger
header := make(http.Header)
for k, v := range m.Header {
header.Set(k, v)
}
b := buf.New(bytes.NewBuffer(m.Body))
defer func() {
if err := b.Close(); err != nil {
logger.Logf(log.ErrorLevel, "failed to close buffer: %v", err)
}
}()
req := &http.Request{
Method: http.MethodPost,
URL: &url.URL{
Scheme: "http",
Host: h.addr,
},
Header: header,
Body: b,
ContentLength: int64(b.Len()),
Host: h.addr,
Close: h.dialOpts.ConnClose,
}
if !h.dialOpts.Stream {
h.Lock()
if h.closed {
h.Unlock()
return io.EOF
}
h.reqList = append(h.reqList, req)
select {
case h.req <- h.reqList[0]:
h.reqList = h.reqList[1:]
default:
}
h.Unlock()
}
// set timeout if its greater than 0
if h.ht.opts.Timeout > time.Duration(0) {
if err := h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)); err != nil {
return err
}
}
return req.Write(h.conn)
}
// Recv receives a message.
func (h *httpTransportClient) Recv(msg *Message) (err error) {
if msg == nil {
return errors.New("message passed in is nil")
}
var req *http.Request
if !h.dialOpts.Stream {
var rc *http.Request
var ok bool
h.Lock()
select {
case rc, ok = <-h.req:
default:
}
if !ok {
if len(h.reqList) == 0 {
h.Unlock()
return io.EOF
}
rc = h.reqList[0]
h.reqList = h.reqList[1:]
}
h.Unlock()
req = rc
}
// set timeout if its greater than 0
if h.ht.opts.Timeout > time.Duration(0) {
if err = h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)); err != nil {
return err
}
}
h.Lock()
defer h.Unlock()
if h.closed {
return io.EOF
}
rsp, err := http.ReadResponse(h.buff, req)
if err != nil {
return err
}
defer func() {
if err2 := rsp.Body.Close(); err2 != nil {
err = errors.Wrap(err2, "failed to close body")
}
}()
b, err := io.ReadAll(rsp.Body)
if err != nil {
return err
}
if rsp.StatusCode != http.StatusOK {
return errors.New(rsp.Status + ": " + string(b))
}
msg.Body = b
if msg.Header == nil {
msg.Header = make(map[string]string, len(rsp.Header))
}
for k, v := range rsp.Header {
if len(v) > 0 {
msg.Header[k] = v[0]
} else {
msg.Header[k] = ""
}
}
return nil
}
func (h *httpTransportClient) Close() error {
if !h.dialOpts.Stream {
h.once.Do(
func() {
h.Lock()
h.buff.Reset(nil)
h.closed = true
h.Unlock()
close(h.req)
},
)
return h.conn.Close()
}
err := h.conn.Close()
h.once.Do(
func() {
h.Lock()
h.buff.Reset(nil)
h.closed = true
h.Unlock()
close(h.req)
},
)
return err
}