本文整理汇总了Golang中github.com/valyala/fasthttp/fasthttputil.NewInmemoryListener函数的典型用法代码示例。如果您正苦于以下问题:Golang NewInmemoryListener函数的具体用法?Golang NewInmemoryListener怎么用?Golang NewInmemoryListener使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了NewInmemoryListener函数的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: benchmarkNetHTTPClientEndToEndBigResponseInmemory
func benchmarkNetHTTPClientEndToEndBigResponseInmemory(b *testing.B, parallelism int) {
bigResponse := createFixedBody(1024 * 1024)
h := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write(bigResponse)
}
ln := fasthttputil.NewInmemoryListener()
ch := make(chan struct{})
go func() {
if err := http.Serve(ln, http.HandlerFunc(h)); err != nil && !strings.Contains(
err.Error(), "use of closed network connection") {
b.Fatalf("error when serving requests: %s", err)
}
close(ch)
}()
c := &http.Client{
Transport: &http.Transport{
Dial: func(_, _ string) (net.Conn, error) { return ln.Dial() },
MaxIdleConnsPerHost: parallelism * runtime.GOMAXPROCS(-1),
},
Timeout: 5 * time.Second,
}
requestURI := "/foo/bar?baz=123"
url := "http://unused.host" + requestURI
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
b.Fatalf("unexpected error: %s", err)
}
for pb.Next() {
resp, err := c.Do(req)
if err != nil {
b.Fatalf("unexpected error: %s", err)
}
if resp.StatusCode != http.StatusOK {
b.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode, http.StatusOK)
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
b.Fatalf("unexpected error when reading response body: %s", err)
}
if !bytes.Equal(bigResponse, body) {
b.Fatalf("unexpected response %q. Expecting %q", body, bigResponse)
}
}
})
ln.Close()
select {
case <-ch:
case <-time.After(time.Second):
b.Fatalf("server wasn't stopped")
}
}
开发者ID:Taik,项目名称:zing-mp3,代码行数:59,代码来源:client_timing_test.go
示例2: TestHostClientMultipleAddrs
func TestHostClientMultipleAddrs(t *testing.T) {
ln := fasthttputil.NewInmemoryListener()
s := &Server{
Handler: func(ctx *RequestCtx) {
ctx.Write(ctx.Host())
ctx.SetConnectionClose()
},
}
serverStopCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverStopCh)
}()
dialsCount := make(map[string]int)
c := &HostClient{
Addr: "foo,bar,baz",
Dial: func(addr string) (net.Conn, error) {
dialsCount[addr]++
return ln.Dial()
},
}
for i := 0; i < 9; i++ {
statusCode, body, err := c.Get(nil, "http://foobar/baz/aaa?bbb=ddd")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if statusCode != StatusOK {
t.Fatalf("unexpected status code %d. Expecting %d", statusCode, StatusOK)
}
if string(body) != "foobar" {
t.Fatalf("unexpected body %q. Expecting %q", body, "foobar")
}
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverStopCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
if len(dialsCount) != 3 {
t.Fatalf("unexpected dialsCount size %d. Expecting 3", len(dialsCount))
}
for _, k := range []string{"foo", "bar", "baz"} {
if dialsCount[k] != 3 {
t.Fatalf("unexpected dialsCount for %q. Expecting 3", k)
}
}
}
开发者ID:hambster,项目名称:fasthttp,代码行数:57,代码来源:client_test.go
示例3: testPipelineClientDoConcurrent
func testPipelineClientDoConcurrent(t *testing.T, concurrency int, maxBatchDelay time.Duration, maxConns int) {
ln := fasthttputil.NewInmemoryListener()
s := &Server{
Handler: func(ctx *RequestCtx) {
ctx.WriteString("OK")
},
}
serverStopCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverStopCh)
}()
c := &PipelineClient{
Dial: func(addr string) (net.Conn, error) {
return ln.Dial()
},
MaxConns: maxConns,
MaxPendingRequests: concurrency,
MaxBatchDelay: maxBatchDelay,
Logger: &customLogger{},
}
clientStopCh := make(chan struct{}, concurrency)
for i := 0; i < concurrency; i++ {
go func() {
testPipelineClientDo(t, c)
clientStopCh <- struct{}{}
}()
}
for i := 0; i < concurrency; i++ {
select {
case <-clientStopCh:
case <-time.After(3 * time.Second):
t.Fatalf("timeout")
}
}
if c.PendingRequests() != 0 {
t.Fatalf("unexpected number of pending requests: %d. Expecting zero", c.PendingRequests())
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverStopCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
开发者ID:insionng,项目名称:vodka,代码行数:56,代码来源:client_test.go
示例4: benchmarkPipelineClient
func benchmarkPipelineClient(b *testing.B, parallelism int) {
h := func(ctx *RequestCtx) {
ctx.WriteString("foobar")
}
ln := fasthttputil.NewInmemoryListener()
ch := make(chan struct{})
go func() {
if err := Serve(ln, h); err != nil {
b.Fatalf("error when serving requests: %s", err)
}
close(ch)
}()
var clients []*PipelineClient
for i := 0; i < runtime.GOMAXPROCS(-1); i++ {
c := &PipelineClient{
Dial: func(addr string) (net.Conn, error) { return ln.Dial() },
ReadBufferSize: 1024 * 1024,
WriteBufferSize: 1024 * 1024,
MaxPendingRequests: parallelism,
}
clients = append(clients, c)
}
clientID := uint32(0)
requestURI := "/foo/bar?baz=123"
url := "http://unused.host" + requestURI
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
n := atomic.AddUint32(&clientID, 1)
c := clients[n%uint32(len(clients))]
var req Request
req.SetRequestURI(url)
var resp Response
for pb.Next() {
if err := c.Do(&req, &resp); err != nil {
b.Fatalf("unexpected error: %s", err)
}
if resp.StatusCode() != StatusOK {
b.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode(), StatusOK)
}
body := resp.Body()
if string(body) != "foobar" {
b.Fatalf("unexpected response %q. Expecting %q", body, "foobar")
}
}
})
ln.Close()
select {
case <-ch:
case <-time.After(time.Second):
b.Fatalf("server wasn't stopped")
}
}
开发者ID:Taik,项目名称:zing-mp3,代码行数:56,代码来源:client_timing_test.go
示例5: benchmark
func benchmark(b *testing.B, h fasthttp.RequestHandler, isTLS bool) {
ln := fasthttputil.NewInmemoryListener()
serverStopCh := startServer(b, ln, h, isTLS)
c := newClient(ln, isTLS)
b.RunParallel(func(pb *testing.PB) {
runRequests(b, pb, c)
})
ln.Close()
<-serverStopCh
}
开发者ID:stellar,项目名称:bridge-server,代码行数:10,代码来源:inmemory_listener_timing_test.go
示例6: TestHostClientMaxConnDuration
func TestHostClientMaxConnDuration(t *testing.T) {
ln := fasthttputil.NewInmemoryListener()
connectionCloseCount := uint32(0)
s := &Server{
Handler: func(ctx *RequestCtx) {
ctx.WriteString("abcd")
if ctx.Request.ConnectionClose() {
atomic.AddUint32(&connectionCloseCount, 1)
}
},
}
serverStopCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverStopCh)
}()
c := &HostClient{
Addr: "foobar",
Dial: func(addr string) (net.Conn, error) {
return ln.Dial()
},
MaxConnDuration: 10 * time.Millisecond,
}
for i := 0; i < 5; i++ {
statusCode, body, err := c.Get(nil, "http://aaaa.com/bbb/cc")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if statusCode != StatusOK {
t.Fatalf("unexpected status code %d. Expecting %d", statusCode, StatusOK)
}
if string(body) != "abcd" {
t.Fatalf("unexpected body %q. Expecting %q", body, "abcd")
}
time.Sleep(c.MaxConnDuration)
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverStopCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
if connectionCloseCount == 0 {
t.Fatalf("expecting at least one 'Connection: close' request header")
}
}
开发者ID:hambster,项目名称:fasthttp,代码行数:55,代码来源:client_test.go
示例7: testWorkerPoolPanicError
func testWorkerPoolPanicError(t *testing.T, wp *workerPool) {
wp.Start()
ln := fasthttputil.NewInmemoryListener()
clientsCount := 10
clientCh := make(chan struct{}, clientsCount)
for i := 0; i < clientsCount; i++ {
go func() {
conn, err := ln.Dial()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
data, err := ioutil.ReadAll(conn)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if len(data) > 0 {
t.Fatalf("unexpected data read: %q. Expecting empty data", data)
}
if err = conn.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
clientCh <- struct{}{}
}()
}
for i := 0; i < clientsCount; i++ {
conn, err := ln.Accept()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !wp.Serve(conn) {
t.Fatalf("worker pool mustn't be full")
}
}
for i := 0; i < clientsCount; i++ {
select {
case <-clientCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
wp.Stop()
}
开发者ID:eurie-inc,项目名称:echo-sample,代码行数:51,代码来源:workerpool_test.go
示例8: TestClientDoTimeoutDisableNormalizing
func TestClientDoTimeoutDisableNormalizing(t *testing.T) {
ln := fasthttputil.NewInmemoryListener()
s := &Server{
Handler: func(ctx *RequestCtx) {
ctx.Response.Header.Set("foo-BAR", "baz")
},
DisableHeaderNamesNormalizing: true,
}
serverStopCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverStopCh)
}()
c := &Client{
Dial: func(addr string) (net.Conn, error) {
return ln.Dial()
},
DisableHeaderNamesNormalizing: true,
}
var req Request
req.SetRequestURI("http://aaaai.com/bsdf?sddfsd")
var resp Response
for i := 0; i < 5; i++ {
if err := c.DoTimeout(&req, &resp, time.Second); err != nil {
t.Fatalf("unexpected error: %s", err)
}
hv := resp.Header.Peek("foo-BAR")
if string(hv) != "baz" {
t.Fatalf("unexpected header value: %q. Expecting %q", hv, "baz")
}
hv = resp.Header.Peek("Foo-Bar")
if len(hv) > 0 {
t.Fatalf("unexpected non-empty header value %q", hv)
}
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverStopCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
开发者ID:insionng,项目名称:vodka,代码行数:51,代码来源:client_test.go
示例9: benchmarkClientEndToEndBigResponseInmemory
func benchmarkClientEndToEndBigResponseInmemory(b *testing.B, parallelism int) {
bigResponse := createFixedBody(1024 * 1024)
h := func(ctx *RequestCtx) {
ctx.SetContentType("text/plain")
ctx.Write(bigResponse)
}
ln := fasthttputil.NewInmemoryListener()
ch := make(chan struct{})
go func() {
if err := Serve(ln, h); err != nil {
b.Fatalf("error when serving requests: %s", err)
}
close(ch)
}()
c := &Client{
MaxConnsPerHost: runtime.GOMAXPROCS(-1) * parallelism,
Dial: func(addr string) (net.Conn, error) { return ln.Dial() },
}
requestURI := "/foo/bar?baz=123"
url := "http://unused.host" + requestURI
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
var req Request
req.SetRequestURI(url)
var resp Response
for pb.Next() {
if err := c.DoTimeout(&req, &resp, 5*time.Second); err != nil {
b.Fatalf("unexpected error: %s", err)
}
if resp.StatusCode() != StatusOK {
b.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode(), StatusOK)
}
body := resp.Body()
if !bytes.Equal(bigResponse, body) {
b.Fatalf("unexpected response %q. Expecting %q", body, bigResponse)
}
}
})
ln.Close()
select {
case <-ch:
case <-time.After(time.Second):
b.Fatalf("server wasn't stopped")
}
}
开发者ID:Taik,项目名称:zing-mp3,代码行数:50,代码来源:client_timing_test.go
示例10: benchmarkNetHTTPClientGetEndToEndInmemory
func benchmarkNetHTTPClientGetEndToEndInmemory(b *testing.B, parallelism int) {
ln := fasthttputil.NewInmemoryListener()
ch := make(chan struct{})
go func() {
if err := http.Serve(ln, http.HandlerFunc(nethttpEchoHandler)); err != nil && !strings.Contains(
err.Error(), "use of closed network connection") {
b.Fatalf("error when serving requests: %s", err)
}
close(ch)
}()
c := &http.Client{
Transport: &http.Transport{
Dial: func(_, _ string) (net.Conn, error) { return ln.Dial() },
MaxIdleConnsPerHost: parallelism * runtime.GOMAXPROCS(-1),
},
}
requestURI := "/foo/bar?baz=123"
url := "http://unused.host" + requestURI
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
resp, err := c.Get(url)
if err != nil {
b.Fatalf("unexpected error: %s", err)
}
if resp.StatusCode != http.StatusOK {
b.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode, http.StatusOK)
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
b.Fatalf("unexpected error when reading response body: %s", err)
}
if string(body) != requestURI {
b.Fatalf("unexpected response %q. Expecting %q", body, requestURI)
}
}
})
ln.Close()
select {
case <-ch:
case <-time.After(time.Second):
b.Fatalf("server wasn't stopped")
}
}
开发者ID:adamzy,项目名称:fasthttp,代码行数:49,代码来源:client_timing_test.go
示例11: benchmarkClientGetEndToEndInmemory
func benchmarkClientGetEndToEndInmemory(b *testing.B, parallelism int) {
ln := fasthttputil.NewInmemoryListener()
ch := make(chan struct{})
go func() {
if err := Serve(ln, fasthttpEchoHandler); err != nil {
b.Fatalf("error when serving requests: %s", err)
}
close(ch)
}()
c := &Client{
MaxConnsPerHost: runtime.GOMAXPROCS(-1) * parallelism,
Dial: func(addr string) (net.Conn, error) { return ln.Dial() },
}
requestURI := "/foo/bar?baz=123"
url := "http://unused.host" + requestURI
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
var buf []byte
for pb.Next() {
statusCode, body, err := c.Get(buf, url)
if err != nil {
b.Fatalf("unexpected error: %s", err)
}
if statusCode != StatusOK {
b.Fatalf("unexpected status code: %d. Expecting %d", statusCode, StatusOK)
}
if string(body) != requestURI {
b.Fatalf("unexpected response %q. Expecting %q", body, requestURI)
}
buf = body
}
})
ln.Close()
select {
case <-ch:
case <-time.After(time.Second):
b.Fatalf("server wasn't stopped")
}
}
开发者ID:adamzy,项目名称:fasthttp,代码行数:43,代码来源:client_timing_test.go
示例12: testWorkerPoolMaxWorkersCount
func testWorkerPoolMaxWorkersCount(t *testing.T) {
ready := make(chan struct{})
wp := &workerPool{
WorkerFunc: func(conn net.Conn) error {
buf := make([]byte, 100)
n, err := conn.Read(buf)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
buf = buf[:n]
if string(buf) != "foobar" {
t.Fatalf("unexpected data read: %q. Expecting %q", buf, "foobar")
}
if _, err = conn.Write([]byte("baz")); err != nil {
t.Fatalf("unexpected error: %s", err)
}
<-ready
return nil
},
MaxWorkersCount: 10,
Logger: defaultLogger,
}
wp.Start()
ln := fasthttputil.NewInmemoryListener()
clientCh := make(chan struct{}, wp.MaxWorkersCount)
for i := 0; i < wp.MaxWorkersCount; i++ {
go func() {
conn, err := ln.Dial()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if _, err = conn.Write([]byte("foobar")); err != nil {
t.Fatalf("unexpected error: %s", err)
}
data, err := ioutil.ReadAll(conn)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if string(data) != "baz" {
t.Fatalf("unexpected value read: %q. Expecting %q", data, "baz")
}
if err = conn.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
clientCh <- struct{}{}
}()
}
for i := 0; i < wp.MaxWorkersCount; i++ {
conn, err := ln.Accept()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !wp.Serve(conn) {
t.Fatalf("worker pool must have enough workers to serve the conn")
}
}
go func() {
if _, err := ln.Dial(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}()
conn, err := ln.Accept()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
for i := 0; i < 5; i++ {
if wp.Serve(conn) {
t.Fatalf("worker pool must be full")
}
}
if err = conn.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(ready)
for i := 0; i < wp.MaxWorkersCount; i++ {
select {
case <-clientCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
wp.Stop()
}
开发者ID:eurie-inc,项目名称:echo-sample,代码行数:95,代码来源:workerpool_test.go
示例13: TestHostClientMaxConnsWithDeadline
func TestHostClientMaxConnsWithDeadline(t *testing.T) {
var (
emptyBodyCount uint8
ln = fasthttputil.NewInmemoryListener()
timeout = 50 * time.Millisecond
wg sync.WaitGroup
)
s := &Server{
Handler: func(ctx *RequestCtx) {
if len(ctx.PostBody()) == 0 {
emptyBodyCount++
}
ctx.WriteString("foo")
},
}
serverStopCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverStopCh)
}()
c := &HostClient{
Addr: "foobar",
Dial: func(addr string) (net.Conn, error) {
return ln.Dial()
},
MaxConns: 1,
}
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
req := AcquireRequest()
req.SetRequestURI("http://foobar/baz")
req.Header.SetMethod("POST")
req.SetBodyString("bar")
resp := AcquireResponse()
for {
if err := c.DoDeadline(req, resp, time.Now().Add(timeout)); err != nil {
if err == ErrNoFreeConns {
time.Sleep(time.Millisecond)
continue
}
t.Fatalf("unexpected error: %s", err)
}
break
}
if resp.StatusCode() != StatusOK {
t.Fatalf("unexpected status code %d. Expecting %d", resp.StatusCode(), StatusOK)
}
body := resp.Body()
if string(body) != "foo" {
t.Fatalf("unexpected body %q. Expecting %q", body, "abcd")
}
}()
}
wg.Wait()
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverStopCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
if emptyBodyCount > 0 {
t.Fatalf("at least one request body was empty")
}
}
开发者ID:insionng,项目名称:vodka,代码行数:80,代码来源:client_test.go
示例14: TestHostClientPendingRequests
func TestHostClientPendingRequests(t *testing.T) {
const concurrency = 10
doneCh := make(chan struct{})
readyCh := make(chan struct{}, concurrency)
s := &Server{
Handler: func(ctx *RequestCtx) {
readyCh <- struct{}{}
<-doneCh
},
}
ln := fasthttputil.NewInmemoryListener()
serverStopCh := make(chan struct{})
go func() {
if err := s.Serve(ln); err != nil {
t.Fatalf("unexpected error: %s", err)
}
close(serverStopCh)
}()
c := &HostClient{
Addr: "foobar",
Dial: func(addr string) (net.Conn, error) {
return ln.Dial()
},
}
pendingRequests := c.PendingRequests()
if pendingRequests != 0 {
t.Fatalf("non-zero pendingRequests: %d", pendingRequests)
}
resultCh := make(chan error, concurrency)
for i := 0; i < concurrency; i++ {
go func() {
req := AcquireRequest()
req.SetRequestURI("http://foobar/baz")
resp := AcquireResponse()
if err := c.DoTimeout(req, resp, 10*time.Second); err != nil {
resultCh <- fmt.Errorf("unexpected error: %s", err)
return
}
if resp.StatusCode() != StatusOK {
resultCh <- fmt.Errorf("unexpected status code %d. Expecting %d", resp.StatusCode(), StatusOK)
return
}
resultCh <- nil
}()
}
// wait while all the requests reach server
for i := 0; i < concurrency; i++ {
select {
case <-readyCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
pendingRequests = c.PendingRequests()
if pendingRequests != concurrency {
t.Fatalf("unexpected pendingRequests: %d. Expecting %d", pendingRequests, concurrency)
}
// unblock request handlers on the server and wait until all the requests are finished.
close(doneCh)
for i := 0; i < concurrency; i++ {
select {
case err := <-resultCh:
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
pendingRequests = c.PendingRequests()
if pendingRequests != 0 {
t.Fatalf("non-zero pendingRequests: %d", pendingRequests)
}
// stop the server
if err := ln.Close(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
select {
case <-serverStopCh:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
开发者ID:insionng,项目名称:vodka,代码行数:93,代码来源:client_test.go
注:本文中的github.com/valyala/fasthttp/fasthttputil.NewInmemoryListener函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论