github.com/songzhibin97/gkit@v1.2.13/README.md (about)

     1  # GKIT
     2  
     3  ```
     4  _____/\\\\\\\\\\\\__/\\\________/\\\__/\\\\\\\\\\\__/\\\\\\\\\\\\\\\_        
     5   ___/\\\//////////__\/\\\_____/\\\//__\/////\\\///__\///////\\\/////__       
     6    __/\\\_____________\/\\\__/\\\//_________\/\\\___________\/\\\_______      
     7     _\/\\\____/\\\\\\\_\/\\\\\\//\\\_________\/\\\___________\/\\\_______     
     8      _\/\\\___\/////\\\_\/\\\//_\//\\\________\/\\\___________\/\\\_______    
     9       _\/\\\_______\/\\\_\/\\\____\//\\\_______\/\\\___________\/\\\_______   
    10        _\/\\\_______\/\\\_\/\\\_____\//\\\______\/\\\___________\/\\\_______  
    11         _\//\\\\\\\\\\\\/__\/\\\______\//\\\__/\\\\\\\\\\\_______\/\\\_______ 
    12          __\////////////____\///________\///__\///////////________\///________                                 
    13  ```
    14   
    15  ##### Translate to: [简体中文](README_zh.md)
    16  
    17  # Project Description
    18  Dedicated to providing microservices and monolithic services of the availability of a collection of basic component tools, drawing on some of the best open source projects such as : `kratos`, `go-kit`, `mosn`, `sentinel`, `gopkg` ... We hope you will support us!
    19  
    20  # Directory structure
    21  ```shell
    22  ├── cache (builds cache-related components)
    23    ├── buffer (provides byte array reuse and io buffer wrapping)
    24    ├── mbuffer (buffer-like implementation) 
    25    ├── local_cache (provides local key-value wrapper implementation for building local caches)
    26    ├── singleflight (provides prevention of duplicate tasks in high concurrency situations, generally used to fill cache miss scenarios)
    27  ├── coding (provides object serialization/deserialization interface, provides json, proto, xml, yaml instance methods)
    28  ├── concurrent (best practices for using channels in concurrency)
    29    ├── fan_in (fan-in pattern, commonly used with multiple producers and one consumer in the producer-consumer model)
    30    ├── fan_out (fan-out mode, often used with a producer-consumer model where there are multiple producers and multiple consumers)
    31    ├── or_done (a concurrency scenario in which any one task is returned immediately after completion)
    32    ├── orderly (keep orderly completion even in concurrent scenarios)
    33    ├── map_reduce 
    34    ├── stream (provides data production stream encapsulation, and implementation of processing streams)
    35    ├── pipeline (concurrency becomes serial)
    36  ├── container (containerized component, providing groups, pools, queues)
    37    ├── group (provides a lazy loading mode for containers, similar to sync.Pool, which uses a key to get the corresponding container instance when used, or generates it if it doesn\'t exist)
    38    ├── pool (provides a wrapped abstraction of pool, and an implementation of the interface using lists)
    39    ├── queue
    40      ├── codel (implements a controlled delay algorithm for columns, and sanctions backlogged tasks)
    41  ├── delayed (delayed tasks - standalone version)
    42  ├── distributed (distributed tasks, provides standardized interfaces and corresponding implementations for redis, mysql, pgsql, mongodb)
    43  ├── downgrade (fusion downgrade related components)
    44  ├── egroup (errgroup, controls component lifecycle)
    45  ├── encrypt (Encryption encapsulation, protection padkey complement)
    46  ├── errors (grpc error handling)
    47  ├── gctuner (pre go1.19 gc optimization tool)
    48  ├── generator (number generator, snowflake)
    49  ├── goroutine (provide goroutine pools, control goroutine spikes)
    50  ├── log (interface logging, use logging component to access)
    51  ├── metrics (interface to metrics)
    52  ├── middleware (middleware interface model definition)
    53  ├── net (network related encapsulation)
    54    ├── tcp
    55  ├── options (option model interfacing)
    56  ├── overload (server adaptive protection, provides bbr interface, monitors deployed server status to select traffic release, protects server availability)
    57    ├── bbr (adaptive flow limiting)
    58  ├── page_token (google aip next token implementation)  
    59  ├── parser (file parsing, proto<->go mutual parsing)
    60    ├── parseGo (parses go to generate pb)
    61    ├── parsePb (parses pb to generate go)
    62  ├── registry (service discovery interfacing, google sre subset implementation)
    63  ├── restrictor (restrict flow, provide token bucket and leaky bucket interface wrappers)
    64    ├── client_throttling (client throttling)
    65    ├── rate 
    66    ├── ratelimite 
    67  ├── structure (common data structure)
    68    ├── hashset (hash tables)
    69    ├── lscq (lock-free unbounded queue, supports arm)
    70    ├── skipmap 
    71    ├── skipset 
    72    ├── zset 
    73  ├── sync
    74      ├── cpu (Get system information for Linux, including cpu mains, cpu usage, etc.)
    75      ├── fastrand (random numbers)
    76      ├── goid (get goroutine id)
    77      ├── mutex (provides trylock, reentrant lock and token reentrant lock)
    78      ├── nanotime (timestamp optimization)
    79      ├── once (a more powerful implementation of once, set the once function to return an error, and retry if it fails)
    80      ├── queue (lock-free queue)
    81      ├── safe (underlying string, slice structure)
    82      ├── stringx (enhanced version of string)
    83      ├── syncx (sync enhancement)
    84      ├── xxhash3 
    85  ├── ternary (ternary expressions)    
    86  ├── timeout (timeout control, full link protection, provides some encapsulated implementation of database processing time)
    87    ├── ctime (link timeout control)
    88    ├── c_json (adapt to database json types)
    89    ├── d_time (adapts to database to store time only)
    90    ├── date (Adapts database to store dates only)
    91    ├── date_struct (Adapts database to store dates only)
    92    ├── datetime (adapter database stores datetime)
    93    ├── datetime_struct (adapter database stores datetime)
    94    ├── stamp (adapter database stores timestamps)
    95    ├── human (provides visual time spacing)
    96  ├── tools 
    97    ├── bind (binding tool, often used with the gin framework to customize the bound data, e.g. binding both query and json)
    98    ├── deepcopy (deep copy)
    99    ├── float (floating point truncation tool)
   100    ├── match (base matcher, match on wildcards)
   101    ├── pointer (pointer tool)
   102    ├── pretty (formatting json)
   103    ├── reflect2value (basic field mapping)
   104    ├── rand_string (random strings)
   105    ├── vto (assignment of functions with the same type, hands free, usually used for vo->do object conversions)
   106      ├── vtoPlus (adds plus support for field, tag and default value binding)
   107  ├── trace (link tracing)
   108  ├── watching (monitor cpu, mum, gc, goroutine and other metrics, automatically dump pprof metrics in case of fluctuations)
   109  └── window (sliding window, supports multi-data type metrics window collection)
   110  
   111  ```
   112  
   113  # Download and use
   114  ```shell
   115  go get github.com/songzhibin97/gkit
   116  ```
   117  
   118  
   119  ## Introduction to the use of components
   120  ## cache
   121  
   122  Cache-related components
   123  > buffer & mbuffer provide similar functionality, buffer has more encapsulation and implements some interfaces to io, while mbuffer is just a memory cache; it is more suitable for short and frequent life cycles.
   124  > local_cache provides a local data cache, and also has some expiry mechanisms, you can set the expiry time, and regularly clean up the expired data, but he is now older, if needed there is a generic version https://github.com/songzhibin97/go-baseutils/blob/main/ app/bcache
   125  > singleflight wraps golang.org/x/sync/singleflight to prevent the effects of changes.
   126  
   127  
   128  ### buffer pool
   129  ```go
   130  package main
   131  
   132  import (
   133  	"fmt"
   134  	"github.com/songzhibin97/gkit/cache/buffer"
   135  )
   136  
   137  func main() {
   138  	// Byte reuse
   139  
   140  	// size 2^6 - 2^18
   141  	// return an integer multiple of 2 rounded upwards cap, len == size
   142  	// Any other special or expanded during runtime will be cleared
   143  	slice := buffer.GetBytes(1024)
   144  	fmt.Println(len(*slice), cap(*slice)) // 1024 1024
   145  
   146  	// Recycle
   147  	// Note: no further references are allowed after recycling
   148  	buffer.PutBytes(slice)
   149  
   150  	// IOByte reuse
   151  
   152  	// io buffer.IoBuffer interface
   153  	GetIoPool(1024)
   154  
   155  	// If an object has already been recycled, referring to the recycled object again will trigger an error
   156  	err := buffer.PutIoPool(io)
   157  	if err != nil {
   158  		// Handle the error 	    
   159  	}
   160  }
   161  ```
   162  
   163  
   164  ### local_cache
   165  ```go
   166  package local_cache
   167  
   168  import (
   169  	"github.com/songzhibin97/gkit/cache/buffer"
   170  	"log"
   171  )
   172  
   173  var ch Cache
   174  
   175  func ExampleNewCache() {
   176  	// default configuration
   177  	// ch = NewCache()
   178  
   179  	// Optional configuration options
   180  
   181  	// Set the interval time
   182  	// SetInternal(interval time.Duration)
   183  
   184  	// Set the default timeout
   185  	// SetDefaultExpire(expire time.Duration)
   186  
   187  	// Set the cycle execution function, the default (not set) is to scan the global to clear expired k
   188  	// SetFn(fn func())
   189  
   190  	// Set the capture function to be called after the deletion is triggered, the set capture function will be called back after the data is deleted
   191  	// SetCapture(capture func(k string, v interface{}))
   192  
   193  	// Set the initialization of the stored member object
   194  	// SetMember(m map[string]Iterator)
   195  
   196  	ch = NewCache(SetInternal(1000).
   197  		SetDefaultExpire(10000).
   198  		SetCapture(func(k string, v interface{}) {
   199  			log.Println(k, v)
   200  		}))
   201  }
   202  
   203  func ExampleCacheStorage() {
   204  	// Set adds cache and overwrites it whether it exists or not
   205  	ch.Set("k1", "v1", DefaultExpire)
   206  
   207  	// SetDefault overrides whether or not it exists
   208  	// Default function mode, default timeout is passed in as the default time to create the cache
   209  	ch.SetDefault("k1", 1)
   210  
   211  	// SetNoExpire
   212  	// partial function mode, default timeout is never expired
   213  	ch.SetNoExpire("k1", 1.1)
   214  
   215  	// Add the cache and throw an exception if it exists
   216  	err := ch.Add("k1", nil, DefaultExpire)
   217  	CacheErrExist(err) // true
   218  
   219  	// Replace throws an error if it is set or not
   220  	err = ch.Replace("k2", make(chan struct{}), DefaultExpire)
   221  	CacheErrNoExist(err) // true
   222  }
   223  
   224  func ExampleGet() {
   225  	// Get the cache based on the key to ensure that kv is removed within the expiration date
   226  	v, ok := ch.Get("k1")
   227  	if !ok {
   228  		// v == nil
   229  	}
   230  	_ = v
   231  
   232  	// GetWithExpire gets the cache based on the key and brings up the timeout
   233  	v, t, ok := ch.GetWithExpire("k1")
   234  	if !ok {
   235  		// v == nil
   236  	}
   237  	// if the timeout is NoExpire t.IsZero() == true
   238  	if t.IsZero() {
   239  		// No timeout is set
   240  	}
   241  
   242  	// Iterator returns all valid objects in the cache
   243  	mp := ch.Iterator()
   244  	for s, iterator := range mp {
   245  		log.Println(s, iterator)
   246  	}
   247  	
   248  	// Count returns the number of members
   249  	log.Println(ch.Count())
   250  }
   251  
   252  func ExampleIncrement() {
   253  	ch.Set("k3", 1, DefaultExpire)
   254  	ch.Set("k4", 1.1, DefaultExpire)
   255  	// Increment adds n to the value corresponding to k n must be a number type
   256  	err := ch.Increment("k3", 1)
   257  	if CacheErrExpire(err) || CacheErrExist(CacheTypeErr) {
   258  		// Not set successfully
   259  	}
   260  	_ = ch.IncrementFloat("k4", 1.1)
   261  
   262  	// If you know the exact type of k to set you can also use the type-determining increment function
   263  	// ch.IncrementInt(k string, v int)
   264  	// ...
   265  	// IncrementFloat32(k string, v flot32) // ch.
   266  	// ...
   267  
   268  	// Decrement the same
   269  }
   270  
   271  func ExampleDelete() {
   272  	// Delete triggers the not-or function if capture is set
   273  	ch.Delete("k1")
   274  
   275  	// DeleteExpire Deletes all expired keys, the default capture is to execute DeleteExpire()
   276  	ch.DeleteExpire()
   277  }
   278  
   279  func ExampleChangeCapture() {
   280  	// Provides a way to change the capture function on the fly
   281  	// ChangeCapture
   282  	ch.ChangeCapture(func(k string, v interface{}) {
   283  		log.Println(k, v)
   284  	})
   285  }
   286  
   287  func ExampleSaveLoad() {
   288  	// Write to a file using go's proprietary gob protocol
   289  
   290  	io := buffer.NewIoBuffer(1000)
   291  
   292  	// Save pass in a w io.Writer argument to write the member members of the cache to w
   293  	_ = ch.Save(io)
   294  
   295  	// SaveFile pass in a path to write to a file
   296  	_ = ch.SaveFile("path")
   297  
   298  	// Load pass in an r io.Reader object read from r and write back to member
   299  	_ = ch.Load(io)
   300  
   301  	// LoadFile pass in path to read the contents of the file
   302  	_ = ch.LoadFile("path")
   303  }
   304  
   305  func ExampleFlush() {
   306  	// Flush to free member members
   307  	ch.Flush()
   308  }
   309  
   310  func ExampleShutdown() {
   311  	// Shutdown frees the object
   312  	ch.Shutdown()
   313  }
   314  ```
   315  
   316  ### singleflight
   317  
   318  Merge back to source
   319  ```go
   320  package main
   321  
   322  import (
   323  	"github.com/songzhibin97/gkit/cache/singleflight"
   324  )
   325  
   326  // getResources: Generally used to go to the database and fetch data
   327  func getResources() (interface{}, error) {
   328  	return "test", nil
   329  }
   330  
   331  // cache: populate the cache with data
   332  func cache(v interface{}) {
   333  	return
   334  }
   335  
   336  func main() {
   337  	f := singleflight.NewSingleFlight()
   338  
   339  	// Synchronize.
   340  	v, err, _ := f.Do("test1", func() (interface{}, error) {
   341  		// Get resources
   342  		return getResources()
   343  	})
   344  	if err != nil {
   345  		// Handle the error
   346  	}
   347  	// store to buffer
   348  	// v is the fetched resource
   349  	cache(v)
   350  
   351  	// asynchronously
   352  	ch := f.DoChan("test2", func() (interface{}, error) {
   353  		// Get resources
   354  		return getResources()
   355  	})
   356  
   357  	// Wait for the resource to be fetched, then return the result via channel
   358  	result := <-ch
   359  	if result.Err != nil {
   360  		// Handle the error
   361  	}
   362  	
   363  	// store to buffer
   364  	// result.Val is the fetched resource
   365  	cache(result.Val)
   366  	
   367  	// try to cancel
   368  	f.Forget("test2")
   369  }
   370  ```
   371  
   372  
   373  ## coding
   374  > Object serialization deserialization interface and instance encapsulation, just import anonymous, such as json `_ "github.com/songzhibin97/gkit/coding/json"` You can also implement the corresponding interface, after registration, the benefit is to control the global serialization object and the use of library unity
   375  
   376  ```go
   377  package main
   378  
   379  import (
   380  	"fmt"
   381  	"github.com/songzhibin97/gkit/coding"
   382  	_ "github.com/songzhibin97/gkit/coding/json" // Be sure to import ahead of time!!!
   383  )
   384  
   385  func main() {
   386  	t := struct {
   387  		Gkit string
   388  		Lever int
   389  	}{"Gkit", 200}
   390  	fmt.Println(coding.GetCode("json").Name())
   391  	GetCode("json").Marshal(t)
   392  	if err != nil {
   393  		fmt.Println(err)
   394  		return
   395  	}
   396  	fmt.Println(string(data)) // {"Gkit": "Gkit", "Lever":200}
   397  	v := struct {
   398  		Gkit string
   399  		Lever int
   400  	}{}
   401  	coding.GetCode("json").Unmarshal(data,&v)
   402  	fmt.Println(v) // { Gkit 200}
   403  }
   404  ```
   405  
   406  ## concurrent
   407  
   408  > Best practices for channel in concurrency, including fan_in,fan_out,map_reduce,or_done,orderly,pipeline,stream,generic version can be found at https://github.com/songzhibin97/go-baseutils/tree/main/app/bconcurrent
   409  
   410  ## container
   411  
   412  > Pool, but you can customize the creation function and replace the initialization function.
   413  > pool pooling object, through the configuration can set the maximum number of connections and the number of waiting connections, synchronous asynchronous acquisition of connections, and connection life cycle management, you can customize the creation function, and replace the initialization function
   414  > codel implement codel algorithm, can be used to limit the flow, and fuse
   415  
   416  ### group
   417  
   418  Lazy loading containers
   419  ```go
   420  package main
   421  
   422  import (
   423  	"fmt"
   424  	"github.com/songzhibin97/gkit/container/group"
   425  )
   426  
   427  func createResources() interface{} {
   428  	return map[int]int{1: 1, 2: 2}
   429  }
   430  
   431  func createResources2() interface{} {
   432  	return []int{1, 2, 3}
   433  }
   434  
   435  func main() {
   436  	// Like sync.Pool
   437  	// initialize a group
   438  	g := group.NewGroup(createResources)
   439  
   440  	// If the key does not exist call the function passed in by NewGroup to create resources
   441  	// If it exists, return the information about the created resource
   442  	v := g.Get("test")
   443  	fmt.Println(v) // map[1:1 2:2]
   444  	v.(map[int]int)[1] = 3
   445  	fmt.Println(v) // map[1:3 2:2]
   446  	v2 := g.Get("test")
   447  	fmt.Println(v2) // map[1:3 2:2]
   448  
   449  	// ReSet resets the initialization function and clears the cached key
   450  	g.ReSet(createResources2)
   451  	v3 := g.Get("test")
   452  	fmt.Println(v3) // []int{1,2,3}
   453  	
   454  	// Clear the cached buffer
   455  	g.Clear()
   456  }
   457  ```
   458  
   459  ### pool
   460  
   461  Similar to a resource pool
   462  ```go
   463  package main
   464  
   465  import (
   466  	"context"
   467  	"fmt"
   468  	"github.com/songzhibin97/gkit/container/pool"
   469  	"time"
   470  )
   471  
   472  var p pool.Pool
   473  
   474  type mock map[string]string
   475  
   476  func (m *mock) Shutdown() error {
   477  	return nil
   478  }
   479  
   480  // getResources: gets resources, returns a resource object that needs to implement the IShutdown interface for resource recycling
   481  func getResources(context.Context) (pool.IShutdown, error) {
   482  	return &mock{"mockKey": "mockValue"}, nil
   483  }
   484  
   485  func main() {
   486  	// pool.NewList(options ...)
   487  	// default configuration
   488  	// p = pool.NewList()
   489  
   490  	// Optional configuration options
   491  
   492  	// Set the number of Pool connections, if == 0 then no limit
   493  	// pool.SetActive(100)
   494  
   495  	// Set the maximum number of free connections
   496  	// pool.SetIdle(20)
   497  
   498  	// Set idle wait time
   499  	// pool.SetIdleTimeout(time.Second)
   500  
   501  	// Set the expected wait
   502  	// pool.SetWait(false,time.Second)
   503  
   504  	// Customize the configuration
   505  	p = pool.NewList(
   506  		pool.SetActive(100).
   507  		pool.SetIdle(20).
   508  		pool.SetIdleTimeout(time.Second).
   509  		SetIdleTimeout(time.Second), pool.SetWait(false, time.Second))
   510  
   511  	// New needs to be instantiated, otherwise it will not get the resource in pool.
   512  	p.NewQueue(getResources)
   513  
   514  	v, err := p.Get(context.TODO())
   515  	if err != nil {
   516  		// Handle the error
   517  	}
   518  	fmt.Println(v) // &map[mockKey:mockValue]
   519  
   520  	// Put: Resource recovery
   521  	// forceClose: true internally help you call Shutdown to recycle, otherwise determine if it is recyclable and mount it on a list
   522  	err = p.Put(context.TODO(), v, false)
   523  	if err != nil {
   524  		// handle the error  	    
   525  	}
   526  	
   527  	// Shutdown reclaims resources, shutting down all resources
   528  	_ = p.Shutdown()
   529  }
   530  ```
   531  
   532  
   533  ### queue
   534  
   535  codel implementation
   536  
   537  ```go
   538  package main
   539  
   540  import (
   541  	"context"
   542  	"fmt"
   543  	"github.com/songzhibin97/gkit/container/queue/codel"
   544  	"github.com/songzhibin97/gkit/overload/bbr"
   545  )
   546  
   547  func main() {
   548  	queue := codel.NewQueue(codel.SetTarget(40), codel.SetInternal(1000))
   549  
   550  	// start reflects CoDel state information
   551  	start := queue.Stat()
   552  	fmt.Println(start)
   553  
   554  	go func() {
   555  		// where the actual consumption takes place
   556  		queue.Pop()
   557  	}()
   558  	if err := queue.Push(context.TODO()); err != nil {
   559  		if err == bbr.LimitExceed {
   560  			// todo handles overload protection errors
   561  		} else {
   562  			// todo handles other errors
   563  		}
   564  	}
   565  }
   566  ```
   567  
   568  ## delayed
   569  
   570  > Stand-alone version of the delay task, using the quadruple heap for implementation, you can customize the monitoring signal, as well as the monitoring time, and the number of work co-processes
   571  
   572  ```go
   573  package main
   574  
   575  import "github.com/songzhibin97/gkit/delayed"
   576  
   577  type mockDelayed struct {
   578  	exec int64
   579  }
   580  
   581  func (m mockDelayed) Do() {
   582  }
   583  
   584  func (m mockDelayed) ExecTime() int64 {
   585  	return m.exec
   586  }
   587  
   588  func (m mockDelayed) Identify() string {
   589  	return "mock"
   590  }
   591  
   592  func main() {
   593  	// Create a delayed object
   594  	// delayed.SetSingle() sets the monitor signal
   595  	// delayed.SetSingleCallback() set the signal callback
   596  	// delayed.SetWorkerNumber() sets the worker concurrently
   597  	// delayed.SetCheckTime() Set the monitoring time
   598  	n := delayed.NewDispatchingDelayed()
   599  
   600  	// add a delayed task
   601  	n.AddDelayed(mockDelayed{exec: 1})
   602  	
   603  	// Force a refresh
   604  	n.Refresh()
   605  	
   606  	// Close
   607  	n.Close()
   608  }
   609  
   610  ```
   611  
   612  ## distributed 
   613  
   614  > Distributed tasks, currently supports db(gorm), mongodb, redis on the backend, redis on the scheduling side, redis on the distributed locking side, including retry mechanisms, and deferred tasks
   615  
   616  ## downgrade
   617  
   618  Meltdown downgrade
   619  
   620  ```go
   621  // Same as github.com/afex/hystrix-go, but in an abstract wrapper to avoid the impact of upgrades on the service
   622  package main
   623  
   624  import (
   625  	"context"
   626  	"github.com/afex/hystrix-go/hystrix"
   627  	"github.com/songzhibin97/gkit/downgrade"
   628  )
   629  
   630  var fuse downgrade.Fuse
   631  
   632  type RunFunc = func() error
   633  type FallbackFunc = func(error) error
   634  type RunFuncC = func(context.Context) error
   635  type FallbackFuncC = func(context.Context, error) error
   636  
   637  var outCH = make(chan struct{}, 1)
   638  
   639  func mockRunFunc() RunFunc {
   640  	return func() error {
   641  		outCH <- struct{}{}
   642  		return nil
   643  	}
   644  }
   645  
   646  func mockFallbackFunc() FallbackFunc {
   647  	return func(err error) error {
   648  		return nil
   649  	}
   650  }
   651  
   652  func mockRunFuncC() RunFuncC {
   653  	return func(ctx context.Context) error {
   654  		return nil
   655  	}
   656  }
   657  
   658  func mockFallbackFuncC() FallbackFuncC {
   659  	return func(ctx context.Context, err error) error {
   660  		return nil
   661  	}
   662  }
   663  
   664  func main() {
   665  	// Get a fuse
   666  	fuse = downgrade.NewFuse()
   667  
   668  	// Leave ConfigureCommand unset and go to the default configuration
   669  	// hystrix.CommandConfig{} set the parameters
   670  	fuse.ConfigureCommand("test", hystrix.CommandConfig{})
   671  
   672  	// Do: execute func() error synchronously, no timeout control until it returns.
   673  	// if return error ! = nil then FallbackFunc is triggered to downgrade
   674  	err := fuse.Do("do", mockRunFunc(), mockFallbackFunc())
   675  	if err != nil {
   676  		// Handle the error
   677  	}
   678  
   679  	// Go: asynchronous execution Return channel
   680  	ch := fuse.Go("go", mockRunFunc(), mockFallbackFunc())
   681  	select {
   682  	case err = <-ch:
   683  	// Handle the error
   684  	case <-outCH:
   685  		break
   686  	}
   687  
   688  	// GoC: Do/Go actually ends up calling GoC, the Do master handles the asynchronous process
   689  	// GoC can be passed into context to ensure link timeout control
   690  	fuse.GoC(context.TODO(), "goc", mockRunFuncC(), mockFallbackFuncC())
   691  }
   692  ```
   693  
   694  ## egroup
   695  
   696  > ErrorGroup, compared with sync.ErrorGroup, adds a fault tolerance mechanism to prevent wild goroutine panic resulting in abnormal system exit
   697  
   698  ```go
   699  // errorGroup 
   700  // Cascade control, if a component has an error, all components in the group will be notified to exit
   701  // Declare lifecycle management
   702  
   703  package main
   704  
   705  import (
   706  	"context"
   707  	"github.com/songzhibin97/gkit/egroup"
   708  	"os"
   709  	"syscall"
   710  	"time"
   711  )
   712  
   713  var admin *egroup.LifeAdmin
   714  
   715  func mockStart() func(ctx context.Context) error {
   716  	return nil
   717  }
   718  
   719  func mockShutdown() func(ctx context.Context) error {
   720  	return nil
   721  }
   722  
   723  type mockLifeAdminer struct{}
   724  
   725  func (m *mockLifeAdminer) Start(ctx context.Context) error {
   726  	return nil
   727  }
   728  
   729  func (m *mockLifeAdminer) Shutdown(ctx context.Context) error {
   730  	return nil
   731  }
   732  
   733  func main() {
   734  	// Default configuration
   735  	// admin = egroup.NewLifeAdmin()
   736  
   737  	// Optional configuration options
   738  
   739  	// set the start timeout
   740  
   741  	// <= 0 no start timeout, note that shutdown notifications should be handled at shutdown
   742  	// egroup.SetStartTimeout(time.Second)
   743  
   744  	// Set the shutdown timeout
   745  	// <=0 no start timeout
   746  	// egroup.SetStopTimeout(time.Second)
   747  
   748  	// Set the set of signals, and the functions to handle them
   749  	// egroup.SetSignal(func(lifeAdmin *LifeAdmin, signal os.Signal) {
   750  	// return
   751  	// }, signal...)
   752  
   753  	admin = egroup.NewLifeAdmin(egroup.SetStartTimeout(time.Second), egroup.SetStopTimeout(time.Second),
   754  		egroup.SetSignal(func(a *egroup.LifeAdmin, signal os.Signal) {
   755  			switch signal {
   756  			case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT:
   757  				a.Shutdown()
   758  			default:
   759  			}
   760  		}))
   761  	
   762  	// Add via struct
   763  	admin.Add(egroup.Member{
   764  		Start:    mockStart(),
   765  		Shutdown: mockShutdown(),
   766  	})
   767  
   768  	// Adapted via interface
   769  	admin.AddMember(&mockLifeAdminer{})
   770  
   771  	// Start
   772  	defer admin.Shutdown()
   773  	if err := admin.Start(); err != nil {
   774  		// Handle errors
   775  		// normal start will hold main
   776  	}
   777  }
   778  
   779  func Demo() {
   780  	// Full demo
   781  	var _admin = egroup.NewLifeAdmin()
   782  
   783  	srv := &http.Server{
   784  		Addr: ":8080",
   785  	}
   786  	// Add a task
   787  	_admin.Add(egroup.Member{
   788  		Start: func(ctx context.Context) error {
   789  			fmt.Println("http start")
   790  			return goroutine.Delegate(ctx, -1, func(ctx context.Context) error {
   791  				return srv.ListenAndServe()
   792  			})
   793  		},
   794  		Shutdown: func(ctx context.Context) error {
   795  			fmt.Println("http shutdown")
   796  			return srv.Shutdown(context.Background())
   797  		},
   798  	})
   799  	// _admin.Start() start
   800  	fmt.Println("error", _admin.Start())
   801  	defer _admin.Shutdown()
   802  }
   803  
   804  ```
   805  
   806  ## encrypt
   807  
   808  > Encryption encapsulation, protection padkey complement
   809  
   810  ## errors
   811  
   812  Wrapping some error handling
   813  
   814  ```go
   815  package main
   816  
   817  import (
   818  	"fmt"
   819  	"net/http"
   820  	"time"
   821  	
   822  	"github.com/songzhibin97/gkit/errors"
   823  )
   824  func main() {
   825  	err := errors.Errorf(http.StatusBadRequest, "reason", "carrying message %s", "test")
   826  	err2 := err.AddMetadata(map[string]string{"time": time.Now().String()}) // Carry meta information
   827  	// err is the original error err2 is the error with meta information
   828  	fmt.Println(errors.Is(err,err2)) // ture
   829  	// err2 can be parsed to get more information
   830  	fmt.Println(err2.Metadata["time"]) // meta
   831  }
   832  ````
   833  
   834  ## gctuner
   835  
   836  > go pre 1.19 gc optimizer
   837  
   838  ```go
   839  
   840  package main
   841  
   842  import "github.com/songzhibin97/gkit/gctuner"
   843  
   844  func main() {
   845  	// Get mem limit from the host machine or cgroup file.
   846  	limit := 4 * 1024 * 1024 * 1024
   847  	threshold := uint64(float64(limit) * 0.7)
   848  
   849  	gctuner.Tuning(threshold)
   850  
   851  	// Friendly input
   852  	gctuner.TuningWithFromHuman("1g")
   853  
   854  	// Auto
   855  	// There may be problems with multiple services in one pod.
   856  	gctuner.TuningWithAuto(false) // Is it a container? Incoming Boolean
   857  }
   858  ```
   859  
   860  ## generator
   861  
   862  Generator
   863  
   864  ### snowflake
   865  
   866  Snowflake algorithm
   867  
   868  ```go
   869  package main
   870  
   871  import (
   872  	"fmt"
   873  	"github.com/songzhibin97/gkit/generator"
   874  	"time"
   875  )
   876  
   877  func main() {
   878  	ids := generator.NewSnowflake(time.Now(), 1)
   879  	nid, err := ids.NextID()
   880  	if err != nil {
   881  		// Handle the error
   882  	}
   883  	fmt.Println(nid)
   884  }
   885  
   886  ```
   887  
   888  ## goroutine
   889  
   890  > Pooling, control exceptions caused by wild goroutine panic, can set maximum capacity, idle time, patrol time, stop timeout, log objects
   891  
   892  ```go
   893  package main
   894  
   895  import (
   896  	"context"
   897  	"fmt"
   898  	"github.com/songzhibin97/gkit/goroutine"
   899  	"time"
   900  )
   901  
   902  var gGroup goroutine.GGroup
   903  
   904  func mockFunc() func() {
   905  	return func() {
   906  		fmt.Println("ok")
   907  	}
   908  }
   909  
   910  func main() {
   911  	// Default configuration
   912  	// gGroup = goroutine.NewGoroutine(context.TODO())
   913  
   914  	// Optional configuration options
   915  
   916  	// set the stop timeout time
   917  	// goroutine.SetStopTimeout(time.Second)
   918  
   919  	// Set the log object
   920  	// goroutine.SetLogger(&testLogger{})
   921  
   922  	// Set the maximum pool size
   923  	// goroutine.SetMax(100)
   924  
   925  	gGroup = goroutine.NewGoroutine(context.TODO(),
   926  		goroutine.SetStopTimeout(time.Second),
   927  		goroutine.SetMax(100),
   928  	)
   929  
   930  	// Add a task
   931  	if !gGroup.AddTask(mockFunc()) {
   932  		// Adding a task failed
   933  	}
   934  
   935  	// Add a task with timeout control
   936  	if !gGroup.AddTaskN(context.TODO(), mockFunc()) {
   937  		// Failed to add task
   938  	}
   939  
   940  	// Modify the pool maximum size
   941  	gGroup.ChangeMax(1000)
   942  
   943  	// Recycle resources
   944  	_ = gGroup.Shutdown()
   945  }
   946  ```
   947  
   948  ## log
   949  
   950  Logging related
   951  
   952  ```go
   953  package main
   954  
   955  import (
   956  	"fmt"
   957  	"github.com/songzhibin97/gkit/log"
   958  )
   959  
   960  type testLogger struct{}
   961  
   962  func (l *testLogger) Print(kv ...interface{}) {
   963  	fmt.Println(kv...)
   964  }
   965  
   966  func main() {
   967  	logs := log.NewHelper(log.DefaultLogger)
   968  	logs.Debug("debug", "v")
   969  	logs.Debugf("%s,%s", "debugf", "v")
   970  	logs.Info("Info", "v")
   971  	logs.Infof("%s,%s", "infof", "v")
   972  	logs.Warn("Warn", "v")
   973  	logs.Warnf("%s,%s", "warnf", "v")
   974  	logs.Error("Error", "v")
   975  	logs.Errorf("%s,%s", "errorf", "v")
   976  	/*
   977  	[debug] message=debugv
   978      [debug] message=debugf,v
   979      [Info] message=Infov
   980      [Info] message=infof,v
   981      [Warn] message=Warnv
   982      [Warn] message=warnf,v
   983      [Error] message=Errorv
   984      [Error] message=errorf,v
   985  	*/
   986  	
   987  	logger := log.DefaultLogger
   988  	logger = log.With(logger, "ts", log.DefaultTimestamp, "caller", log.DefaultCaller)
   989  	logger.Log(log.LevelInfo, "msg", "helloworld")
   990  	// [Info] ts=2021-06-10T13:41:35+08:00 caller=main.go:8 msg=helloworld
   991  }
   992  ```
   993  
   994  ## metrics
   995  
   996  Provides a metrics interface for implementing monitoring configurations
   997  ```go
   998  package main
   999  
  1000  type Counter interface {
  1001  	With(lvs ...string) Counter
  1002  	Inc()
  1003  	Add(delta float64)
  1004  }
  1005  
  1006  // Gauge is metrics gauge.
  1007  type Gauge interface {
  1008  	With(lvs ...string) Gauge
  1009  	Set(value float64)
  1010  	Add(delta float64)
  1011  	Sub(delta float64)
  1012  }
  1013  
  1014  // Observer is metrics observer.
  1015  type Observer interface {
  1016  	With(lvs ...string) Observer
  1017  	Observe(float64)
  1018  }
  1019  ```
  1020  
  1021  ## middleware
  1022  
  1023  Middleware interface model definition
  1024  ```go
  1025  package main
  1026  
  1027  import (
  1028  	"context"
  1029  	"fmt"
  1030  	"github.com/songzhibin97/gkit/middleware"
  1031  	)
  1032  
  1033  func annotate(s string) middleware.MiddleWare {
  1034  	return func(next middleware.Endpoint) middleware.Endpoint {
  1035  		return func(ctx context.Context, request interface{}) (interface{}, error) {
  1036  			fmt.Println(s, "pre")
  1037  			defer fmt.Println(s, "post")
  1038  			return next(ctx, request)
  1039  		}
  1040  	}
  1041  }
  1042  
  1043  func myEndpoint(context.Context, interface{}) (interface{}, error) {
  1044  	fmt.Println("my endpoint!")
  1045  	return struct{}{}, nil
  1046  }
  1047  
  1048  var (
  1049  	ctx = context.Background()
  1050  	req = struct{}{}
  1051  )
  1052  
  1053  func main() {
  1054      e := middleware.Chain(
  1055  		annotate("first"),
  1056  		annotate("second"),
  1057  		annotate("third"),
  1058  	)(myEndpoint)
  1059  
  1060  	if _, err := e(ctx, req); err != nil {
  1061  		panic(err)
  1062  	}
  1063  	// Output.
  1064  	// first pre
  1065  	// second pre
  1066  	// third pre
  1067  	// my endpoint!
  1068  	// third post
  1069  	// second post
  1070  	// first post
  1071  }
  1072  ```
  1073  
  1074  ## net
  1075  
  1076  Network related encapsulation
  1077  
  1078  ### tcp
  1079  ```go
  1080      // Send data to the other side, with a retry mechanism
  1081      Send(data []byte, retry *Retry) error
  1082  
  1083      // Accept data
  1084      // length == 0 Read from Conn once and return immediately
  1085      // length < 0 Receive all data from Conn and return it until there is no more data
  1086      // length > 0 Receive the corresponding data from Conn and return it
  1087      Recv(length int, retry *Retry) ([]byte, error) 
  1088  
  1089      // Read a line of '\n'
  1090      RecvLine(retry *Retry) ([]byte, error) 
  1091  
  1092      // Read a link that has timed out
  1093      RecvWithTimeout(length int, timeout time.Duration, retry *Retry) ([]byte, error) 
  1094  
  1095      // Write data to a link that has timed out
  1096      SendWithTimeout(data []byte, timeout time.Duration, retry *Retry) error
  1097  
  1098      // Write data and read back
  1099      SendRecv(data []byte, length int, retry *Retry) ([]byte, error)
  1100  
  1101      // Write data to and read from a link that has timed out
  1102      SendRecvWithTimeout(data []byte, timeout time.Duration, length int, retry *Retry) ([]byte, error)
  1103  ```
  1104  
  1105  ## options
  1106  
  1107  Options mode interface
  1108  
  1109  
  1110  ## overload
  1111  > Overload protection, internal current limiting using bbr algorithm
  1112  
  1113  **general use**
  1114  
  1115  ```go
  1116  package main
  1117  
  1118  import (
  1119  	"context"
  1120  	"github.com/songzhibin97/gkit/overload"
  1121  	"github.com/songzhibin97/gkit/overload/bbr"
  1122  )
  1123  
  1124  func main() {
  1125  	// Common use
  1126  	
  1127  	// Create the Group first
  1128  	group := bbr.NewGroup()
  1129  	// If it doesn't exist, it will be created
  1130  	limiter := group.Get("key")
  1131  	f, err := limiter.Allow(context.TODO())
  1132  	if err != nil {
  1133  		// means it is overloaded and the service is not allowed to access it
  1134  		return
  1135  	}
  1136  	// Op: the actual operation type of the traffic write-back record indicator
  1137  	f(overload.DoneInfo{Op: overload.Success})
  1138  }
  1139  ```
  1140  
  1141  **Middleware application**
  1142  
  1143  ```go
  1144  package main
  1145  
  1146  import (
  1147  	"context"
  1148  	"github.com/songzhibin97/gkit/overload"
  1149  	"github.com/songzhibin97/gkit/overload/bbr"
  1150  )
  1151  
  1152  func main() {
  1153  	// Common use
  1154  
  1155  	// Create the Group first
  1156  	group := bbr.NewGroup()
  1157  	// If it doesn't exist, it will be created
  1158  	limiter := group.Get("key")
  1159  	f, err := limiter.Allow(context.TODO())
  1160  	if err != nil {
  1161  		// means it is overloaded and the service is not allowed to access it
  1162  		return
  1163  	}
  1164  	// Op: the actual operation type of the traffic write-back record indicator
  1165  	f(overload.DoneInfo{Op: overload.Success})
  1166  
  1167  	// Create Group middleware
  1168  	middle := bbr.NewLimiter()
  1169  
  1170  	// in the middleware 
  1171  	// The ctx carries these two configurable valid data
  1172  	// You can get the limiter type via the ctx.Set
  1173  
  1174  	// Configure to get the limiter type, you can get different limiter according to different api
  1175  	ctx := context.WithValue(context.TODO(), bbr.LimitKey, "key")
  1176  
  1177  	// Configurable to report success or not
  1178  	// must be of type overload.
  1179  	ctx = context.WithValue(ctx, bbr.LimitOp, overload.Success)
  1180  
  1181  	_ = middle
  1182  }
  1183  ```
  1184  
  1185  ## page_token
  1186  > https://google.aip.dev/158 Google Pagination
  1187  > The options mode allows you to configure a custom maximum page value, maximum number of elements per page, set the encryption key, and expiration time, page_token to effectively prevent crawlers and page flip attacks, and to limit the interface concurrency.
  1188  
  1189  ```go
  1190  package main
  1191  
  1192  import "github.com/songzhibin97/gkit/page_token"
  1193  
  1194  func main() {
  1195     	n := NewTokenGenerate("test") // Unique identification of the resource, and the option to pass the above
  1196  	// 10000 is the total number
  1197  	// Generate page_token
  1198  	// start - end start and end address, tk is next_token
  1199  	start, end, tk, err := n.ProcessPageTokens(10000, 100, "") // 0,100, tk
  1200  	start, end, ntk, err := n.ProcessPageTokens(10000, 100, tk) // 100,200,ntk
  1201  	n.GetIndex(ntk) // 200
  1202  }
  1203  ```
  1204  
  1205  ## parser
  1206  
  1207  Provides `.go` file to `.pb` and `.pb` to `.go` 
  1208  `.go` files to `.pb` are more feature-rich, for example, providing spot staking code injection and de-duplication recognition
  1209  
  1210  ```go
  1211  package main
  1212  
  1213  import (
  1214  	"fmt"
  1215  	"github.com/songzhibin97/gkit/parse/parseGo"
  1216  	"github.com/songzhibin97/gkit/parse/parsePb"
  1217  )
  1218  
  1219  func main() {
  1220  	pgo, err := parseGo.ParseGo("gkit/parse/demo/demo.api")
  1221  	if err != nil {
  1222  		panic(err)
  1223  	}
  1224  	r := pgo.(*parseGo.GoParsePB)
  1225  	for _, note := range r.Note {
  1226  		fmt.Println(note.Text, note.Pos(), note.End())
  1227  	}
  1228  	// Output the string, if you need to import the file yourself
  1229  	fmt.Println(r.Generate())
  1230  
  1231  	// Pile injection
  1232  	_ = r.PileDriving("", "start", "end", "var _ = 1")
  1233      
  1234  	// Dismounting
  1235  	_ = r.PileDismantle("var _ = 1")
  1236  	
  1237  	ppb, err := parsePb.ParsePb("GKit/parse/demo/test.proto")
  1238  	if err != nil {
  1239  		panic(err)
  1240  	}
  1241  	// Output the string, if you need to import the file yourself
  1242  	fmt.Println(ppb.Generate())
  1243  }
  1244  ```
  1245  
  1246  ## registry
  1247  
  1248  > Provides a generic interface for registration discovery, external dependencies using the generic interface, and a fixed instance structure
  1249  > Service discovery provides a variety of algorithms, from the common subset algorithm to the latest rock_steadier_subset(https://dl.acm.org/doi/10.1145/3570937)
  1250  
  1251  
  1252  ## restrictor
  1253  
  1254  flow limiter
  1255  
  1256  ### rate
  1257  
  1258  leakage bucket
  1259  
  1260  ```go
  1261  package main
  1262  
  1263  import (
  1264  	"context"
  1265  	rate2 "github.com/songzhibin97/gkit/restrictor/rate"
  1266  	"golang.org/x/time/rate"
  1267  	"time"
  1268  )
  1269  
  1270  func main() {
  1271  	// The first argument is r Limit, which represents how many tokens can be generated into the Token bucket per second; Limit is actually an alias for float64
  1272  	// The second argument is b int. b represents the size of the Token bucket.
  1273  	// limit := Every(100 * time.Millisecond).
  1274  	// limiter := rate.NewLimiter(limit, 4)
  1275  	// The above means putting a Token in the bucket every 100ms, which essentially means generating 10 a second.
  1276  
  1277  	// rate: golang.org/x/time/rate
  1278  	limiter := rate.NewLimiter(2, 4)
  1279  
  1280  	af, wf := rate2.NewRate(limiter)
  1281  
  1282  	// af.Allow() bool: take 1 token by default
  1283  	// af.Allow() == af.AllowN(time.Now(), 1)
  1284  	af.Allow()
  1285  
  1286  	// af.AllowN(ctx,n) bool: can take N tokens
  1287  	af.AllowN(time.Now(), 5)
  1288  
  1289  	// wf.Wait(ctx) err: wait for ctx to time out, default takes 1 token
  1290  	// wf.Wait(ctx) == wf.WaitN(ctx, 1) 
  1291  	_ = wf.Wait(context.TODO())
  1292  
  1293  	// wf.WaitN(ctx, n) err: wait for ctx to time out, can take N tokens
  1294  	_ = wf.WaitN(context.TODO(), 5)
  1295  }
  1296  ```
  1297  
  1298  ### ratelimite
  1299  
  1300  Token bucket
  1301  
  1302  ```go
  1303  package main
  1304  
  1305  import (
  1306  	"context"
  1307  	"github.com/juju/ratelimit"
  1308  	ratelimit2 "github.com/songzhibin97/gkit/restrictor/ratelimite"
  1309  	"time"
  1310  )
  1311  
  1312  func main() {
  1313  	// ratelimit:github.com/juju/ratelimit
  1314  	bucket := ratelimit.NewBucket(time.Second/2, 4)
  1315  
  1316  	af, wf := ratelimit2.NewRateLimit(bucket)
  1317  	// af.Allow() bool: takes 1 token by default
  1318  	// af.Allow() == af.AllowN(time.Now(), 1)
  1319  	af.Allow()
  1320  
  1321  	// af.AllowN(ctx,n) bool: can take N tokens
  1322  	af.AllowN(time.Now(), 5)
  1323  
  1324  	// wf.Wait(ctx) err: wait for ctx to time out, default takes 1 token
  1325  	// wf.Wait(ctx) == wf.WaitN(ctx, 1) 
  1326  	_ = wf.Wait(context.TODO())
  1327  
  1328  	// wf.WaitN(ctx, n) err: wait for ctx to time out, can take N tokens
  1329  	_ = wf.WaitN(context.TODO(), 5)
  1330  }
  1331  ```
  1332  
  1333  ## structure (common data structures)
  1334  
  1335  ### hashset
  1336  
  1337  ```go
  1338  package main
  1339  
  1340  func main() {
  1341  	l := hashset.NewInt()
  1342  
  1343  	for _, v := range []int{10, 12, 15} {
  1344  		l.Add(v)
  1345  	}
  1346  
  1347  	if l.Contains(10) {
  1348  		fmt.Println("hashset contains 10")
  1349  	}
  1350  
  1351  	l.Range(func(value int) bool {
  1352  		fmt.Println("hashset range found ", value)
  1353  		return true
  1354  	})
  1355  
  1356  	l.Remove(15)
  1357  	fmt.Printf("hashset contains %d items\r\n", l.Len())
  1358  }
  1359  ```
  1360  
  1361  
  1362  ### lscq
  1363  
  1364  ```go
  1365  package main
  1366  
  1367  func main() {
  1368      l := lscq.NewUint64()
  1369  	
  1370  	ok := l.Enqueue(1)
  1371  	if !ok {
  1372  		panic("enqueue failed")
  1373      }   
  1374  	v, err := l.Dequeue()
  1375  	if err != nil {
  1376  		panic("dequeue failed")
  1377      }
  1378  	fmt.Println("lscq dequeue value:", v)
  1379  }
  1380  ```
  1381  
  1382  
  1383  ### skipmap 
  1384  
  1385  ```go
  1386  package main
  1387  
  1388  func main() {
  1389       m := skipmap.NewInt()
  1390  
  1391  	// Correctness.
  1392  	m.Store(123, "123")
  1393  	m.Load(123)
  1394  	m.Delete(123)
  1395  	m.LoadOrStore(123)
  1396  	m.LoadAndDelete(123)
  1397  }
  1398  ```
  1399  
  1400  ### skipset 
  1401  
  1402  ```go
  1403  package main
  1404  func Example() {
  1405  	l := skipset.NewInt()
  1406  
  1407  	for _, v := range []int{10, 12, 15} {
  1408  		if l.Add(v) {
  1409  			fmt.Println("skipset add", v)
  1410  		}
  1411  	}
  1412  
  1413  	if l.Contains(10) {
  1414  		fmt.Println("skipset contains 10")
  1415  	}
  1416  
  1417  	l.Range(func(value int) bool {
  1418  		fmt.Println("skipset range found ", value)
  1419  		return true
  1420  	})
  1421  
  1422  	l.Remove(15)
  1423  	fmt.Printf("skipset contains %d items\r\n", l.Len())
  1424  }
  1425  ```
  1426  
  1427  
  1428  ### zset View corresponding readme 
  1429  
  1430  ## sys
  1431  ### mutex
  1432      Lock-related wrappers (implements trylock, reentrant locks, etc., reentrant token locks, can also get lock indicator data)
  1433  ```go
  1434  package main
  1435  
  1436  func main() {
  1437       // Get the lock
  1438      lk := mutex.NewMutex()
  1439      // Try to get a lock
  1440      if lk.TryLock() {
  1441      	// Get the lock
  1442      	defer lk.Unlock()
  1443      }
  1444      // Failed to execute other logic
  1445      
  1446      lk.Count() // get the number of locks waiting
  1447      
  1448      lk.IsLocked() // whether the lock is held
  1449      
  1450      lk.IsWoken() // whether a waiter has been woken up internally
  1451      
  1452      lk.IsStarving() // whether it is in starvation mode
  1453      
  1454      // Reentrant locks
  1455      // can be acquired multiple times in the same goroutine
  1456      rvlk := mutex.NewRecursiveMutex() 
  1457      rvlk.Lock()
  1458      defer rvlk.Unlock()
  1459      
  1460      // token reentrant lock
  1461      // Pass in the same token to enable the reentrant function
  1462      tklk := mutex.NewTokenRecursiveMutex()
  1463      tklk.Lock(token)
  1464      defer tklk.Unlock(token)
  1465  }
  1466  ```
  1467  
  1468  
  1469  ## ternary
  1470  
  1471  > Simple implementation of ternary expressions
  1472  > The generic version can be used **[go-baseutils](https://github.com/songzhibin97/go-baseutils/tree/main/base/bternaryexpr)**
  1473  > Be careful not to use the null pointer directly for point arithmetic, as it needs to be called first as an entry, the solution can be to close the incoming function
  1474  
  1475  ```go
  1476  package main
  1477  
  1478  import "github.com/songzhibin97/gkit/ternary"
  1479  
  1480  func main() {
  1481      ternary.ReturnInt(true, 1, 2)  // 1
  1482  }
  1483  ```
  1484  
  1485  ## timeout
  1486  
  1487  > Timeout control between services (and a structure to handle the time format)
  1488  
  1489  ```go
  1490  package main
  1491  
  1492  import (
  1493  	"context"
  1494  	"github.com/songzhibin97/gkit/timeout"
  1495  	"time"
  1496  )
  1497  
  1498  func main() {
  1499  	// The timeout.Shrink method provides link-wide timeout control
  1500  	// Just pass in a ctx of the parent node and the timeout to be set, and he will check for you if the ctx has been set before.
  1501  	// If the timeout has been set, it will be compared with the timeout you currently set, and the smallest one will be set to ensure that the link timeout is not affected downstream.
  1502  	// d: represents the remaining timeout period
  1503  	// nCtx: the new context object
  1504  	// cancel: returns a cancel() method if the timeout was actually set successfully, or an invalid cancel if it was not, but don't worry, it can still be called normally
  1505  	d, nCtx, cancel := timeout.Shrink(context.Background(), 5*time.Second)
  1506  	// d as needed 
  1507  	// Generally determine the downstream timeout for the service, if d is too small you can just drop it
  1508  	select {
  1509  	case <-nCtx.Done():
  1510  		cancel()
  1511  	default:
  1512  		// ...
  1513  	}
  1514  	_ = d
  1515  }
  1516  ```
  1517  Other(currently, gorm also has a related type that is supported.)
  1518  > timeout.DbJSON // provides some functionality in db json format
  1519  > timeout.DTime // provides some functionality in db 15:04:05 format
  1520  > DateStruct // provides some functionality in db 15:04:05 format Embedded in struct mode
  1521  > Date // provides some functionality in db 2006-01-02 format
  1522  > DateTime // provides some functions in db 2006-01-02 15:04:05 format
  1523  > DateTimeStruct // provides some functions in db 2006-01-02 15:04:05 format Embed mode as struct
  1524  > timeout.Stamp // provides some functionality in db timestamp format
  1525  
  1526  ```go
  1527  package main
  1528  
  1529  import (
  1530  	"github.com/songzhibin97/gkit/timeout"
  1531  	"gorm.io/driver/mysql"
  1532  	"gorm.io/gorm"
  1533  	"time"
  1534  )
  1535  
  1536  type GoStruct struct {
  1537  	DateTime timeout.DateTime
  1538  	DTime    timeout.DTime
  1539  	Date     timeout.Date
  1540  }
  1541  
  1542  func main() {
  1543  	// refer to https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
  1544  	dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  1545  	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  1546  	if err != nil {
  1547  		panic(err)
  1548  	}
  1549  	db.AutoMigrate(&GoStruct{})
  1550  	db.Create(&GoStruct{
  1551  		DateTime: timeout.DateTime(time.Now()).
  1552  		DTime: timeout.DTime(time.Now()).
  1553  		Date: timeout.Date(time.Now()).
  1554  	})
  1555  	v := &GoStruct{}
  1556  	db.Find(v) // successfully found
  1557  }
  1558  
  1559  ```
  1560  
  1561  
  1562  
  1563  ## tools
  1564  
  1565  ### bind
  1566  ```go
  1567  
  1568  package main
  1569  
  1570  // Provide an all-in-one bind tool for gin
  1571  import (
  1572  	"github.com/songzhibin97/gkit/tools/bind"
  1573  
  1574  	"github.com/gin-gonic/gin"
  1575  )
  1576  
  1577  type Test struct {
  1578  	Json string `json: "json" form: "json,default=jjjson"`
  1579  	Query string `json: "query" form: "query"`
  1580  }
  1581  
  1582  func main() {
  1583  	r := gin.Default()
  1584  	r.POST("test", func(c * gin.Context) {
  1585  		t := Test{}
  1586  		// url : 127.0.0.1:8080/test?query=query
  1587  		// {
  1588  		// "json": "json".
  1589  		// "query": "query"
  1590  		// }
  1591  		// err := c.ShouldBindWith(&t, bind.CreateBindAll(c.ContentType()), bind.)
  1592  		// Custom binding object
  1593  		// err := c.ShouldBindWith(&t, bind.CreateBindAll(c.ContentType(), bind.SetSelectorParse([]bind.Binding{})))
  1594  		if err != nil {
  1595  			c.JSON(200, err)
  1596  			return
  1597  		}
  1598  		c.JSON(200, t)
  1599  	})
  1600  	r.Run(":8080")
  1601  }
  1602  ```
  1603  
  1604  ### votodo
  1605  ```go
  1606  package main
  1607  
  1608  import "github.com/songzhibin97/gkit/tools/vto"
  1609  
  1610  type CP struct {
  1611  	Z1 int `default: "1"`
  1612  	Z2 string `default: "z2"`
  1613  }
  1614  
  1615  func main() {
  1616  	c1 := CP{
  1617  		Z1: 22,
  1618  		Z2: "33",
  1619  	}
  1620  	c2 := CP{}
  1621  	c3 := CP{}
  1622  	_ = vto.VoToDo(&c2,&c1)
  1623  	// c2 CP{ Z1: 22, Z2: "33"}
  1624  	// same name same type execution copy
  1625  	// must be dst, src must pass pointer type
  1626  	
  1627  	// v1.1.2 New default tag
  1628  	_ = vto.VoToDo(&c2,&c3)
  1629  	// c2 CP{ Z1: 1, Z2: "z2"}
  1630  	// same name same type execution copy
  1631  	// must dst, src must pass pointer type
  1632  	
  1633  }
  1634  ```
  1635  
  1636  ### votodoPlus
  1637  
  1638  Added field &tag & default value
  1639  
  1640  ## window
  1641  
  1642  Provide indicator windows
  1643  ```go
  1644  package main
  1645  
  1646  import (
  1647  	"fmt"
  1648  	"github.com/songzhibin97/gkit/window"
  1649  	"time"
  1650  )
  1651  func main() {
  1652  	w := window.NewWindow()
  1653  	slice := []window.Index{
  1654  		{Name: "1", Score: 1}, {Name: "2", Score: 2}.
  1655  		{Name: "2", Score: 2}, {Name: "3", Score: 3}.
  1656  		{Name: "2", Score: 2}, {Name: "3", Score: 3}.
  1657  		{Name: "4", Score: 4}, {Name: "3", Score: 3}.
  1658  		{Name: "5", Score: 5}, {Name: "2", Score: 2}.
  1659  		{Name: "6", Score: 6}, {Name: "5", Score: 5}.
  1660  	}
  1661  	/*
  1662  			[{1 1} {2 2}]
  1663  		    [{2 4} {3 3} {1 1}]
  1664  		    [{1 1} {2 6} {3 6}]
  1665  		    [{3 9} {4 4} {1 1} {2 6}]
  1666  		    [{1 1} {2 8} {3 9} {4 4} {5 5}]
  1667  		    [{5 10} {3 9} {2 6} {4 4} {6 6}]
  1668  	*/
  1669  	for i := 0; i < len(slice); i += 2 {
  1670  		w.AddIndex(slice[i].Name, slice[i].Score)
  1671  		w.AddIndex(slice[i+1].Name, slice[i+1].Score)
  1672  		time.Sleep(time.Second)
  1673  		fmt.Println(w.Show())
  1674  	}
  1675  }
  1676  ```
  1677  
  1678  ## trace
  1679  Link tracing
  1680  
  1681  ```go
  1682  package main
  1683  
  1684  import (
  1685  	"context"
  1686  	"fmt"
  1687  
  1688  	gtrace "github.com/songzhibin97/gkit/trace"
  1689  	"go.opentelemetry.io/otel/trace"
  1690  )
  1691  
  1692  type _Transport struct {
  1693  }
  1694  
  1695  func (tr *_Transport) Get(key string) string {
  1696  	panic("implement me")
  1697  }
  1698  
  1699  func (tr *_Transport) Set(key string, value string) {
  1700  	panic("implement me")
  1701  }
  1702  
  1703  func (tr *_Transport) Keys() []string {
  1704  	panic("implement me")
  1705  }
  1706  func main() {
  1707  	// trace.WithServer() server side using middleware
  1708  	// trace.WithClient() client using middleware
  1709  	tracer := gtrace.NewTracer(trace.SpanKindServer)
  1710  	ctx, span := tracer.Start(context.Background(), "Using gkit", &_Transport{})
  1711  	fmt.Println(span)
  1712  	defer tracer.End(ctx, span, "replay", nil)
  1713  }
  1714  ```
  1715  
  1716  ## watching
  1717  
  1718  System monitoring (includes cpu, mum, gc, goroutine, etc. window monitoring, dump pprof after preset fluctuation values)