1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-17 16:12:42 +08:00

优化range引用

This commit is contained in:
2022-07-04 12:01:44 +08:00
parent 44304f5b16
commit 886723997e
8 changed files with 143 additions and 12 deletions

View File

@ -26,7 +26,8 @@ func NewBloomFilter() *BloomFilter {
} }
func (bf *BloomFilter) Add(value string) { func (bf *BloomFilter) Add(value string) {
for _, f := range bf.funcs { funcs := bf.funcs[:]
for _, f := range funcs {
bf.set.Set(f.hash(value)) bf.set.Set(f.hash(value))
} }
} }
@ -36,7 +37,9 @@ func (bf *BloomFilter) Contains(value string) bool {
return false return false
} }
ret := true ret := true
for _, f := range bf.funcs {
funcs := bf.funcs[:]
for _, f := range funcs {
ret = ret && bf.set.Test(f.hash(value)) ret = ret && bf.set.Test(f.hash(value))
} }
return ret return ret

View File

@ -16,7 +16,9 @@ func (r BytesResult) Hex() string {
func (r BytesResult) UppercaseHex() string { func (r BytesResult) UppercaseHex() string {
dst := make([]byte, hex.EncodedLen(len(r))) dst := make([]byte, hex.EncodedLen(len(r)))
j := 0 j := 0
for _, v := range r {
re := r[:]
for _, v := range re {
dst[j] = hextable[v>>4] dst[j] = hextable[v>>4]
dst[j+1] = hextable[v&0x0f] dst[j+1] = hextable[v&0x0f]
j += 2 j += 2

View File

@ -42,7 +42,8 @@ func (z *zipPackage) Write(out *os.File) error {
zipWriter := zip.NewWriter(out) zipWriter := zip.NewWriter(out)
defer zipWriter.Close() defer zipWriter.Close()
for _, f := range z.files { files := z.files
for _, f := range files {
fileWriter, err := zipWriter.Create(f.name) fileWriter, err := zipWriter.Create(f.name)
if err != nil { if err != nil {
return err return err

View File

@ -88,7 +88,8 @@ func (m *sorted_map[K, V]) Iter() <-chan *Entry[K, V] {
} }
func (m *sorted_map[K, V]) ForEach(f func(K, V) bool) { func (m *sorted_map[K, V]) ForEach(f func(K, V) bool) {
for _, k := range m.keys { keys := m.keys[:]
for _, k := range keys {
if v, ok := m.Get(k); ok { if v, ok := m.Get(k); ok {
if f(k, v) { if f(k, v) {
break break

81
panic/panic.go Normal file
View File

@ -0,0 +1,81 @@
package panic
import (
"context"
"fmt"
"runtime/debug"
)
type Panic struct {
R any
Stack []byte
}
func (p Panic) String() string {
return fmt.Sprintf("%v\n%s", p.R, p.Stack)
}
type PanicGroup struct {
panics chan Panic // 致命错误通知
dones chan int // 协程完成通知
jobs chan int // 并发数量
jobN int32 // 工作协程数量
}
func NewPanicGroup(maxConcurrent int) *PanicGroup {
return &PanicGroup{
panics: make(chan Panic, 8),
dones: make(chan int, 8),
jobs: make(chan int, maxConcurrent),
}
}
func (g *PanicGroup) Go(f func()) *PanicGroup {
g.jobN++
go func() {
g.jobs <- 1
defer func() {
<-g.jobs
// go 语言只能在自己的协程中捕获自己的 panic
// 如果不处理,整个*进程*都会退出
if r := recover(); r != nil {
g.panics <- Panic{R: r, Stack: debug.Stack()}
// 如果发生 panic 就不再通知 Wait() 已完成
// 不然就可能出现 g.jobN 为 0 但 g.panics 非空
// 的情况,此时 Wait() 方法需要在正常结束的分支
// 中再额外检查是否发生了 panic非常麻烦
return
}
g.dones <- 1
}()
f()
}()
return g
}
func (g *PanicGroup) Wait(ctx context.Context) error {
if g.jobN == 0 {
panic("no job to wait")
}
for {
select {
case <-g.dones: // 协程正常结束
g.jobN--
if g.jobN == 0 {
return nil
}
case p := <-g.panics: // 协程有 panic
panic(p)
case <-ctx.Done():
// 整个 ctx 结束,超时或者调用方主动取消
// 子协程应该共用该 ctx都会收到相同的结束信号
// 不需要在这里再去通知各协程结束(实现起来也麻烦)
return ctx.Err()
}
}
}

32
panic/panic_test.go Normal file
View File

@ -0,0 +1,32 @@
package panic
import (
"context"
"fmt"
"testing"
"time"
)
func TestPanic(t *testing.T) {
defer func() {
t.Log("捕捉异常")
if e := recover(); e != nil {
if err, ok := e.(error); ok {
t.Log(err.Error())
}
t.Log("格式化:", e)
}
}()
g := NewPanicGroup(10)
g.Go(func() {
panic("1243")
})
if err := g.Wait(context.Background()); err != nil {
panic(err)
}
time.Sleep(1 * time.Second)
fmt.Println("这条消息可打印")
}

View File

@ -40,7 +40,9 @@ func (s *mapSorter[T]) Desc() *mapSorter[T] {
func (s *mapSorter[T]) Join(sep string, f func(k string, v T) string) string { func (s *mapSorter[T]) Join(sep string, f func(k string, v T) string) string {
slice := make([]string, 0, len(s.m)) slice := make([]string, 0, len(s.m))
for _, k := range s.keys {
keys := s.keys[:]
for _, k := range keys {
slice = append(slice, f(k, s.m[k])) slice = append(slice, f(k, s.m[k]))
} }
@ -53,7 +55,9 @@ func (s *mapSorter[T]) Keys() []string {
func (s *mapSorter[T]) Values() []T { func (s *mapSorter[T]) Values() []T {
ret := make([]T, 0, len(s.m)) ret := make([]T, 0, len(s.m))
for _, k := range s.keys {
keys := s.keys[:]
for _, k := range keys {
ret = append(ret, s.m[k]) ret = append(ret, s.m[k])
} }

View File

@ -36,7 +36,8 @@ func (s *Struct) Kind() reflect.Kind {
func (s *Struct) Names() []string { func (s *Struct) Names() []string {
names := make([]string, len(s.fields)) names := make([]string, len(s.fields))
for i, f := range s.fields { fields := s.fields[:]
for i, f := range fields {
names[i] = f.name names[i] = f.name
} }
@ -45,7 +46,9 @@ func (s *Struct) Names() []string {
func (s *Struct) Values() []any { func (s *Struct) Values() []any {
values := make([]any, 0, len(s.fields)) values := make([]any, 0, len(s.fields))
for _, fi := range s.fields {
fields := s.fields[:]
for _, fi := range fields {
v := s.value.FieldByName(fi.name) v := s.value.FieldByName(fi.name)
values = append(values, v.Interface()) values = append(values, v.Interface())
} }
@ -54,7 +57,8 @@ func (s *Struct) Values() []any {
} }
func (s *Struct) IsZero() bool { func (s *Struct) IsZero() bool {
for _, fi := range s.fields { fields := s.fields[:]
for _, fi := range fields {
source := s.value.FieldByName(fi.name) source := s.value.FieldByName(fi.name)
if !source.IsZero() { if !source.IsZero() {
return false return false
@ -66,7 +70,9 @@ func (s *Struct) IsZero() bool {
func (s *Struct) ToMap() map[string]any { func (s *Struct) ToMap() map[string]any {
m := make(map[string]any, len(s.fields)) m := make(map[string]any, len(s.fields))
for _, fi := range s.fields {
fields := s.fields[:]
for _, fi := range fields {
source := s.value.FieldByName(fi.name) source := s.value.FieldByName(fi.name)
if fi.shouldIgnore(source) { if fi.shouldIgnore(source) {
continue continue
@ -109,7 +115,8 @@ func (s *Struct) Copy(dest any) error {
} }
func (s *Struct) getByName(name string) (field, bool) { func (s *Struct) getByName(name string) (field, bool) {
for i := range s.fields { fields := s.fields[:]
for i := range fields {
f := s.fields[i] f := s.fields[i]
if f.name == name { if f.name == name {
return f, true return f, true