Record a stepping record of a go project

wrong description

  • Created a script in the go project and wrote a main function
  • Which uses a modelgithub.com/link1st/go-stress-testing/stress
import (
    "fmt"
    // "github.com/dji/go-stress-testing/stress"
	"github.com/link1st/go-stress-testing/stress"
    "net/http"
    "time"
)
  • When executing go run xxx.go, an error is reported
queries.go:6:2: no required module provides package github.com/link1st/go-stress-testing/stress; to add it:
        go get github.com/link1st/go-stress-testing/stress
  • Prompt to use go get github.com/link1st/go-stress-testing/stresscommand to download missing modules
  • Sure enough, the error is still reported after execution
go: github.com/link1st/go-stress-testing/stress: no matching versions for query "upgrade"
  • Indicates that there is no newer version available for the module
  • Specified version:go get github.com/link1st/go-stress-testing/stress@latest
  • Still getting an error that the target version cannot be obtained

Search for module version information on github

  • Search techniques language:go model_nameare as follows
    • image.png
  • View module version information
  • image.png

Specify the version to install

go get github.com/link1st/go-stress-testing/stress@v1.0.5
  • Things don't always go well, still report errors
    • go: github.com/link1st/go-stress-testing/[email protected]: invalid version: unknown revision stress/v1.0.5

Manual build

  • After consulting the information, you can manually build the project to install the module, similar to the second-party library in the maven project

  1. First of all, find out where the dependent modules of the go project are installed
    1. under $GOPATH/pkg/mod/the directory
    2. Similar to the .m2 directory of maven's local repository. The storage structure of the module is also similar
  2. Then download github.com/link1st/go-stress-testing/stressthe project source code of
    1. The cloned code defaults to the master branch
    2. git checkout v1.0.5
  3. nextgo build
    • -o: Specifies the name and path of the output file.
    • -v: Print out the name of the compiled Go package.
    • -a: Force recompile all packages without using cached results.
    • -race: Enables the data race detector to identify and report data races in Go programs.
    • -tags: Specifies the build tags to use.
  4. full commandgo build -o /Users/duzhihao/go/pkg/mod/github.com/link1st/go-stress-testing/[email protected] main.go
    1. But it still doesn't work

root of the problem

  1. The required package isgithub.com/link1st/go-stress-testing/stress
  2. Be clear about how to interpret this package
    1. github.com: The module comes from github
    2. link1st: The author is link1st
    3. go-stress-testing: Belongs to project go-stress-testing
    4. stress: The stress module under the project
  3. Go to the github project to find this module
  4. image.png
  5. Good guy, there is no stress module at all.

final solution

I found the source code under the stress module by other means, and there are four files in total.

task.go

package stress

import (
    "context"
    "errors"
)

// Task represents a stress testing task, which consists of a name, a RunFunc function and optional StopFunc function
type Task struct {
    
    
    Name      string
    RunFunc   func() error
    StopFunc  func() error
    Context   context.Context
    Cancel    context.CancelFunc
}

// Run runs the Task and returns a TestResult
func (t *Task) Run() *TestResult {
    
    
    var requests uint64
    var errors uint64

    for {
    
    
        select {
    
    
        case <-t.Context.Done():
            return &TestResult{
    
    
                Requests: requests,
                Errors:   errors,
            }
        default:
            if err := t.RunFunc(); err != nil {
    
    
                errors++
            }
            requests++
        }
    }
}

// NewTask returns a new Task with the given name and RunFunc function
func NewTask(name string, runFunc func() error) *Task {
    
    
    ctx, cancel := context.WithCancel(context.Background())
    return &Task{
    
    
        Name:     name,
        RunFunc:  runFunc,
        Context:  ctx,
        Cancel:   cancel,
    }
}

// NewTimedTask returns a new Task with the given name, RunFunc function and duration
func NewTimedTask(name string, runFunc func() error, duration int) *Task {
    
    
    ctx, cancel := context.WithTimeout(context.Background(), Duration(duration)*time.Second)
    return &Task{
    
    
        Name:     name,
        RunFunc:  runFunc,
        StopFunc: cancel,
        Context:  ctx,
        Cancel:   cancel,
    }
}

// Stop stops the Task
func (t *Task) Stop() error {
    
    
    if t.StopFunc == nil {
    
    
        return errors.New("Stop function is not defined")
    }

    return t.StopFunc()
}

scene.go

package stress


import (
    "sync"
    "sync/atomic"
    "time"
)


// Scene represents a stress testing scene, which consists of multiple tasks
type Scene struct {
    
    
    Name        string
    Frequency   time.Duration
    Duration    time.Duration
    SetupFunc   func() error
    CleanupFunc func() error
    tasks       []*Task
}


// AddTask adds a new Task to the Scene
func (s *Scene) AddTask(task *Task) {
    
    
    s.tasks = append(s.tasks, task)
}


// Run runs the Scene and returns a TestResult
func (s *Scene) Run() *TestResult {
    
    
    resCh := make(chan *TestResult)
    wg := sync.WaitGroup{
    
    }


    wg.Add(len(s.tasks))


    for _, task := range s.tasks {
    
    
        go func(task *Task) {
    
    
            defer wg.Done()
            resCh <- task.Run()
        }(task)
    }


    if s.SetupFunc != nil {
    
    
        if err := s.SetupFunc(); err != nil {
    
    
            panic(err)
        }
    }


    ticker := time.NewTicker(s.Frequency)
    stop := make(chan bool)


    go func() {
    
    
        time.Sleep(s.Duration)
        close(stop)
    }()


    var requests uint64
    var errors uint64


loop:
    for {
    
    
        select {
    
    
        case <-ticker.C:
            for _, task := range s.tasks {
    
    
                for i := 0; i < requestsPerTask; i++ {
    
    
                    if err := task.RunFunc(); err != nil {
    
    
                        atomic.AddUint64(&errors, 1)
                    }
                    atomic.AddUint64(&requests, 1)
                }
            }
        case res := <-resCh:
            atomic.AddUint64(&requests, res.Requests)
            atomic.AddUint64(&errors, res.Errors)
        case <-stop:
            break loop
        }
    }


    ticker.Stop()


    if s.CleanupFunc != nil {
    
    
        if err := s.CleanupFunc(); err != nil {
    
    
            panic(err)
        }
    }


    wg.Wait()


    elapsed := time.Duration(requests) * time.Second / time.Duration(rps)
    return &TestResult{
    
    
        Requests: requests,
        Errors:   errors,
        Rps:      rps,
        Elapsed:  elapsed,
    }
}


// NewScene returns a new Scene with the given name and default settings
func NewScene(name string) *Scene {
    
    
    return &Scene{
    
    
        Name:      name,
        Frequency: time.Second,
        Duration:  10 * time.Second,
        SetupFunc: func() error {
    
    
            return nil
        },
        CleanupFunc: func() error {
    
    
            return nil
        },
    }
}

test_result.go

package stress


import "time"


// TestResult represents the result of a stress test
type TestResult struct {
    
    
    Requests uint64
    Errors   uint64
    Rps      uint64
    Elapsed  time.Duration
}

utils.go

package stress


import "time"


const (
    requestsPerTask = 100
    rps             = 100
)


// Duration is an int that can be used with the time package
type Duration int


func (d Duration) String() string {
    
    
    return time.Duration(d * time.Second).String()
}

It should be noted that the codes of these go files are not reliable, and logic adaptation needs to be carried out according to requirements in practical applications.

Guess you like

Origin blog.csdn.net/GoNewWay/article/details/130997639